2 * \file lib/signature.c
9 #include <rpm/rpmtypes.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 "lib/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 rasprintf(&pgpvbin, "%sv", pgpbin);
86 if (stat(pgpvbin, &st) == 0)
87 saved_pgp_version = PGP_5;
88 else if (stat(pgpbin, &st) == 0)
89 saved_pgp_version = PGP_2;
91 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 struct indexEntry_s entry;
143 struct entryInfo_s 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 memset(&entry, 0, sizeof(entry));
181 memset(&info, 0, sizeof(info));
183 nb = (il * sizeof(struct entryInfo_s)) + dl;
184 ei = xmalloc(sizeof(il) + sizeof(dl) + nb);
187 pe = (entryInfo) &ei[2];
188 dataStart = (unsigned char *) (pe + il);
189 if ((xx = timedRead(fd, (void *)pe, nb)) != nb) {
191 _("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx);
195 /* Check (and convert) the 1st tag element. */
196 xx = headerVerifyInfo(1, dl, pe, &entry.info, 0);
198 rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
199 0, entry.info.tag, entry.info.type,
200 entry.info.offset, entry.info.count);
204 /* Is there an immutable header region tag? */
205 if (entry.info.tag == RPMTAG_HEADERSIGNATURES
206 && entry.info.type == RPM_BIN_TYPE
207 && entry.info.count == REGION_TAG_COUNT)
210 if (entry.info.offset >= dl) {
212 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
213 entry.info.tag, entry.info.type,
214 entry.info.offset, entry.info.count);
218 /* Is there an immutable header region tag trailer? */
219 dataEnd = dataStart + entry.info.offset;
220 (void) memcpy(&info, dataEnd, REGION_TAG_COUNT);
221 /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */
222 if (info.tag == htonl(RPMTAG_HEADERIMAGE)) {
223 rpmSigTag stag = htonl(RPMTAG_HEADERSIGNATURES);
225 memcpy(dataEnd, &stag, sizeof(stag));
227 dataEnd += REGION_TAG_COUNT;
229 xx = headerVerifyInfo(1, dl, &info, &entry.info, 1);
231 !((entry.info.tag == RPMTAG_HEADERSIGNATURES || entry.info.tag == RPMTAG_HEADERIMAGE)
232 && entry.info.type == RPM_BIN_TYPE
233 && entry.info.count == REGION_TAG_COUNT))
236 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
237 entry.info.tag, entry.info.type,
238 entry.info.offset, entry.info.count);
241 memset(&info, 0, sizeof(info));
243 /* Is the no. of tags in the region less than the total no. of tags? */
244 ril = entry.info.offset/sizeof(*pe);
245 if ((entry.info.offset % sizeof(*pe)) || ril > il) {
246 rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
251 /* Sanity check signature tags */
252 memset(&info, 0, sizeof(info));
253 for (i = 1; i < il; i++) {
254 xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0);
257 _("sigh tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
258 i, entry.info.tag, entry.info.type,
259 entry.info.offset, entry.info.count);
264 /* OK, blob looks sane, load the header. */
265 sigh = headerLoad(ei);
267 rasprintf(&buf, _("sigh load: BAD\n"));
270 sigh->flags |= HEADERFLAG_ALLOCATED;
272 { size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
273 size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */
275 rpm_off_t * archSize = NULL;
277 /* Position at beginning of header. */
278 if (pad && (trc = timedRead(fd, (void *)block, pad)) != pad) {
280 _("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc);
284 /* Print package component sizes. */
285 if (headerGetEntry(sigh, RPMSIGTAG_SIZE, NULL,(rpm_data_t *)&archSize, NULL)) {
286 rc = printSize(fd, sigSize, pad, *archSize);
287 if (rc != RPMRC_OK) {
289 _("sigh sigSize(%zd): BAD, fstat(2) failed\n"), sigSize);
296 if (sighp && sigh && rc == RPMRC_OK)
297 *sighp = headerLink(sigh);
298 sigh = headerFree(sigh);
309 int rpmWriteSignature(FD_t fd, Header sigh)
311 static uint8_t buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
315 rc = headerWrite(fd, sigh, HEADER_MAGIC_YES);
319 sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
320 pad = (8 - (sigSize % 8)) % 8;
322 if (Fwrite(buf, sizeof(buf[0]), pad, fd) != pad)
325 rpmlog(RPMLOG_DEBUG, "Signature: size(%d)+pad(%d)\n", sigSize, pad);
329 Header rpmNewSignature(void)
331 Header sigh = headerNew();
335 Header rpmFreeSignature(Header sigh)
337 return headerFree(sigh);
341 * Generate PGP signature(s) for a header+payload file.
342 * @param file header+payload file name
343 * @retval *sigTagp signature tag
344 * @retval *pktp signature packet(s)
345 * @retval *pktlenp signature packet(s) length
346 * @param passPhrase private key pass phrase
347 * @return 0 on success, 1 on failure
349 static int makePGPSignature(const char * file, rpmSigTag * sigTagp,
350 uint8_t ** pktp, size_t * pktlenp,
351 const char * passPhrase)
353 char * sigfile = NULL;
362 pgpDigParams sigp = NULL;
364 int rc = 1; /* assume failure */
366 rasprintf(&sigfile, "%s.sig", file);
368 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
369 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
371 inpipe[0] = inpipe[1] = 0;
372 if (pipe(inpipe) < 0) {
373 rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
377 if (!(pid = fork())) {
378 const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
382 (void) dup2(inpipe[0], 3);
383 (void) close(inpipe[1]);
385 (void) dosetenv("PGPPASSFD", "3", 1);
386 if (pgp_path && *pgp_path != '\0')
387 (void) dosetenv("PGPPATH", pgp_path, 1);
389 /* dosetenv("PGPPASS", passPhrase, 1); */
391 unsetenv("MALLOC_CHECK_");
392 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
395 cmd = rpmExpand("%{?__pgp_sign_cmd}", NULL);
396 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
398 rc = execve(av[0], av+1, environ);
401 cmd = rpmExpand("%{?__pgp5_sign_cmd}", NULL);
402 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
404 rc = execve(av[0], av+1, environ);
407 case PGP_NOTDETECTED:
412 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "pgp",
417 delMacro(NULL, "__plaintext_filename");
418 delMacro(NULL, "__signature_filename");
420 fpipe = fdopen(inpipe[1], "w");
421 (void) close(inpipe[0]);
423 fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
424 (void) fclose(fpipe);
427 (void)waitpid(pid, &status, 0);
428 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
429 rpmlog(RPMLOG_ERR, _("pgp failed\n"));
433 if (stat(sigfile, &st)) {
434 /* PGP failed to write signature */
435 if (sigfile) (void) unlink(sigfile); /* Just in case */
436 rpmlog(RPMLOG_ERR, _("pgp failed to write signature\n"));
440 *pktlenp = st.st_size;
441 rpmlog(RPMLOG_DEBUG, "PGP sig size: %zd\n", *pktlenp);
442 *pktp = xmalloc(*pktlenp);
447 fd = Fopen(sigfile, "r.fdio");
448 if (fd != NULL && !Ferror(fd)) {
449 rc = timedRead(fd, (void *)*pktp, *pktlenp);
450 if (sigfile) (void) unlink(sigfile);
453 if (rc != *pktlenp) {
454 *pktp = _free(*pktp);
455 rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
460 rpmlog(RPMLOG_DEBUG, "Got %zd bytes of PGP sig\n", *pktlenp);
464 /* Parse the signature, change signature tag as appropriate. */
467 (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
468 sigp = &dig->signature;
470 dig = pgpFreeDig(dig);
480 * Generate GPG signature(s) for a header+payload file.
481 * @param file header+payload file name
482 * @retval *sigTagp signature tag
483 * @retval *pktp signature packet(s)
484 * @retval *pktlenp signature packet(s) length
485 * @param passPhrase private key pass phrase
486 * @return 0 on success, 1 on failure
488 static int makeGPGSignature(const char * file, rpmSigTag * sigTagp,
489 uint8_t ** pktp, size_t * pktlenp,
490 const char * passPhrase)
492 char * sigfile = NULL;
500 pgpDigParams sigp = NULL;
501 int rc = 1; /* assume failure */
503 rasprintf(&sigfile, "%s.sig", file);
505 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
506 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
508 inpipe[0] = inpipe[1] = 0;
509 if (pipe(inpipe) < 0) {
510 rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
514 if (!(pid = fork())) {
515 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
517 (void) dup2(inpipe[0], 3);
518 (void) close(inpipe[1]);
520 if (gpg_path && *gpg_path != '\0')
521 (void) dosetenv("GNUPGHOME", gpg_path, 1);
522 (void) dosetenv("LC_ALL", "C", 1);
524 unsetenv("MALLOC_CHECK_");
525 cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
526 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
528 rc = execve(av[0], av+1, environ);
530 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
535 delMacro(NULL, "__plaintext_filename");
536 delMacro(NULL, "__signature_filename");
538 fpipe = fdopen(inpipe[1], "w");
539 (void) close(inpipe[0]);
541 fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
542 (void) fclose(fpipe);
545 (void) waitpid(pid, &status, 0);
546 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
547 rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
551 if (stat(sigfile, &st)) {
552 /* GPG failed to write signature */
553 rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n"));
557 *pktlenp = st.st_size;
558 rpmlog(RPMLOG_DEBUG, "GPG sig size: %zd\n", *pktlenp);
559 *pktp = xmalloc(*pktlenp);
564 fd = Fopen(sigfile, "r.fdio");
565 if (fd != NULL && !Ferror(fd)) {
566 rc = timedRead(fd, (void *)*pktp, *pktlenp);
569 if (rc != *pktlenp) {
570 *pktp = _free(*pktp);
571 rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
576 rpmlog(RPMLOG_DEBUG, "Got %zd bytes of GPG sig\n", *pktlenp);
578 /* Parse the signature, change signature tag as appropriate. */
581 (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
582 sigp = &dig->signature;
590 /* XXX check MD5 hash too? */
591 if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
592 *sigTagp = RPMSIGTAG_PGP;
594 case RPMSIGTAG_PGP5: /* XXX legacy */
596 if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
597 *sigTagp = RPMSIGTAG_GPG;
600 /* XXX check MD5 hash too? */
601 if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
602 *sigTagp = RPMSIGTAG_RSA;
605 if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
606 *sigTagp = RPMSIGTAG_DSA;
609 case RPMSIGTAG_LEMD5_1:
610 case RPMSIGTAG_LEMD5_2:
611 case RPMSIGTAG_BADSHA1_1:
612 case RPMSIGTAG_BADSHA1_2:
613 case RPMSIGTAG_PAYLOADSIZE:
617 dig = pgpFreeDig(dig);
621 (void) unlink(sigfile);
628 * Generate header only signature(s) from a header+payload file.
629 * @param sigh signature header
630 * @param file header+payload file name
631 * @param sigTag type of signature(s) to add
632 * @param passPhrase private key pass phrase
633 * @return 0 on success, -1 on failure
635 static int makeHDRSignature(Header sigh, const char * file, rpmSigTag sigTag,
636 const char * passPhrase)
640 uint8_t * pkt = NULL;
644 int ret = -1; /* assume failure. */
649 case RPMSIGTAG_PGP5: /* XXX legacy */
655 fd = Fopen(file, "r.fdio");
656 if (fd == NULL || Ferror(fd))
658 h = headerRead(fd, HEADER_MAGIC_YES);
661 (void) Fclose(fd); fd = NULL;
663 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
669 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)
673 _("Immutable header region could not be read. "
674 "Corrupted package?\n"));
678 ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
679 (void) rpmDigestUpdate(ctx, header_magic, sizeof(header_magic));
680 (void) rpmDigestUpdate(ctx, uh, uhc);
681 (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1);
682 uh = headerFreeData(uh, uht);
688 if (!headerAddEntry(sigh, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1))
693 fd = Fopen(file, "r.fdio");
694 if (fd == NULL || Ferror(fd))
696 h = headerRead(fd, HEADER_MAGIC_YES);
700 fd = rpmMkTempFile(NULL, &fn);
701 if (fd == NULL || Ferror(fd))
703 if (headerWrite(fd, h, HEADER_MAGIC_YES))
705 (void) Fclose(fd); fd = NULL;
706 if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
707 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
712 fd = Fopen(file, "r.fdio");
713 if (fd == NULL || Ferror(fd))
715 h = headerRead(fd, HEADER_MAGIC_YES);
719 fd = rpmMkTempFile(NULL, &fn);
720 if (fd == NULL || Ferror(fd))
722 if (headerWrite(fd, h, HEADER_MAGIC_YES))
724 (void) Fclose(fd); fd = NULL;
725 if (makePGPSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
726 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
731 case RPMSIGTAG_LEMD5_1:
732 case RPMSIGTAG_LEMD5_2:
733 case RPMSIGTAG_BADSHA1_1:
734 case RPMSIGTAG_BADSHA1_2:
735 case RPMSIGTAG_PAYLOADSIZE:
747 if (fd != NULL) (void) Fclose(fd);
751 int rpmAddSignature(Header sigh, const char * file, rpmSigTag sigTag,
752 const char * passPhrase)
755 uint8_t * pkt = NULL;
757 int ret = -1; /* assume failure. */
761 if (stat(file, &st) != 0)
764 if (!headerAddEntry(sigh, sigTag, RPM_INT32_TYPE, &pktlen, 1))
770 pkt = xcalloc(pktlen, sizeof(*pkt));
771 if (rpmDoDigest(PGPHASHALGO_MD5, file, 0, pkt, NULL)
772 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
776 case RPMSIGTAG_PGP5: /* XXX legacy */
778 if (makePGPSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
779 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
781 #ifdef NOTYET /* XXX needs hdrmd5ctx, like hdrsha1ctx. */
782 /* XXX Piggyback a header-only RSA signature as well. */
783 ret = makeHDRSignature(sigh, file, RPMSIGTAG_RSA, passPhrase);
788 if (makeGPGSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
789 || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
791 /* XXX Piggyback a header-only DSA signature as well. */
792 ret = makeHDRSignature(sigh, file, RPMSIGTAG_DSA, passPhrase);
797 ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
800 case RPMSIGTAG_LEMD5_1:
801 case RPMSIGTAG_LEMD5_2:
802 case RPMSIGTAG_BADSHA1_1:
803 case RPMSIGTAG_BADSHA1_2:
804 case RPMSIGTAG_PAYLOADSIZE:
812 static int checkPassPhrase(const char * passPhrase, const rpmSigTag sigTag)
814 int passPhrasePipe[2];
819 passPhrasePipe[0] = passPhrasePipe[1] = 0;
820 xx = pipe(passPhrasePipe);
821 if (!(pid = fork())) {
826 xx = close(STDIN_FILENO);
827 xx = close(STDOUT_FILENO);
828 xx = close(passPhrasePipe[1]);
829 if (! rpmIsVerbose())
830 xx = close(STDERR_FILENO);
831 if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
832 xx = dup2(fdno, STDIN_FILENO);
835 if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
836 xx = dup2(fdno, STDOUT_FILENO);
839 xx = dup2(passPhrasePipe[0], 3);
841 unsetenv("MALLOC_CHECK_");
845 { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
847 if (gpg_path && *gpg_path != '\0')
848 (void) dosetenv("GNUPGHOME", gpg_path, 1);
850 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
851 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
853 rc = execve(av[0], av+1, environ);
855 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
859 case RPMSIGTAG_PGP5: /* XXX legacy */
861 { const char *pgp_path = rpmExpand("%{?_pgp_path}", NULL);
865 (void) dosetenv("PGPPASSFD", "3", 1);
866 if (pgp_path && *pgp_path != '\0')
867 xx = dosetenv("PGPPATH", pgp_path, 1);
869 if ((path = rpmDetectPGPVersion(&pgpVer)) != NULL) {
872 cmd = rpmExpand("%{?__pgp_check_password_cmd}", NULL);
873 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
875 rc = execve(av[0], av+1, environ);
877 case PGP_5: /* XXX legacy */
878 cmd = rpmExpand("%{?__pgp5_check_password_cmd}", NULL);
879 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
881 rc = execve(av[0], av+1, environ);
884 case PGP_NOTDETECTED:
888 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "pgp",
892 default: /* This case should have been screened out long ago. */
893 rpmlog(RPMLOG_ERR, _("Invalid %%_signature spec in macro file\n"));
899 xx = close(passPhrasePipe[0]);
900 xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
901 xx = write(passPhrasePipe[1], "\n", 1);
902 xx = close(passPhrasePipe[1]);
904 (void) waitpid(pid, &status, 0);
906 return ((!WIFEXITED(status) || WEXITSTATUS(status)) ? 1 : 0);
909 char * rpmGetPassPhrase(const char * prompt, const rpmSigTag sigTag)
917 { char *name = rpmExpand("%{?_gpg_name}", NULL);
918 aok = (name && *name != '\0');
924 _("You must set \"%%_gpg_name\" in your macro file\n"));
927 case RPMSIGTAG_PGP5: /* XXX legacy */
929 { char *name = rpmExpand("%{?_pgp_name}", NULL);
930 aok = (name && *name != '\0');
936 _("You must set \"%%_pgp_name\" in your macro file\n"));
939 /* Currently the calling function (rpm.c:main) is checking this and
940 * doing a better job. This section should never be accessed.
942 rpmlog(RPMLOG_ERR, _("Invalid %%_signature spec in macro file\n"));
947 pass = getpass( (prompt ? prompt : "") );
949 if (checkPassPhrase(pass, sigTag))
956 static const char * rpmSigString(rpmRC res)
960 case RPMRC_OK: str = "OK"; break;
961 case RPMRC_FAIL: str = "BAD"; break;
962 case RPMRC_NOKEY: str = "NOKEY"; break;
963 case RPMRC_NOTTRUSTED: str = "NOTRUSTED"; break;
965 case RPMRC_NOTFOUND: str = "UNKNOWN"; break;
971 verifySizeSignature(const rpmts ts, char ** msg)
973 rpm_constdata_t sig = rpmtsSig(ts);
974 pgpDig dig = rpmtsDig(ts);
976 size_t size = 0x7fffffff;
977 const char * title = _("Header+Payload size:");
982 if (sig == NULL || dig == NULL || dig->nbytes == 0) {
984 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
988 memcpy(&size, sig, sizeof(size));
990 if (size != dig->nbytes) {
992 rasprintf(msg, "%s %s Expected(%zd) != (%zd)\n", title,
993 rpmSigString(res), size, dig->nbytes);
996 rasprintf(msg, "%s %s (%zd)\n", title, rpmSigString(res), dig->nbytes);
1004 verifyMD5Signature(const rpmts ts, char ** msg,
1007 rpm_constdata_t sig = rpmtsSig(ts);
1008 size_t siglen = rpmtsSiglen(ts);
1009 pgpDig dig = rpmtsDig(ts);
1011 uint8_t * md5sum = NULL;
1014 const char *title = _("MD5 digest:");
1016 assert(msg != NULL);
1019 if (md5ctx == NULL || sig == NULL || dig == NULL) {
1021 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
1025 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1026 (void) rpmDigestFinal(rpmDigestDup(md5ctx),
1027 (void **)&md5sum, &md5len, 0);
1028 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1029 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1031 md5 = pgpHexStr(md5sum, md5len);
1032 if (md5len != siglen || memcmp(md5sum, sig, md5len)) {
1034 char *hex = pgpHexStr(sig, siglen);
1035 rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title,
1036 rpmSigString(res), hex, md5);
1040 rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), md5);
1045 md5sum = _free(md5sum);
1050 * Verify header immutable region SHA1 digest.
1051 * @param ts transaction set
1052 * @retval msg verbose success/failure text
1054 * @return RPMRC_OK on success
1057 verifySHA1Signature(const rpmts ts, char ** msg,
1060 const char *sig = rpmtsSig(ts);
1062 size_t siglen = rpmtsSiglen(ts);
1064 pgpDig dig = rpmtsDig(ts);
1067 const char *title = _("Header SHA1 digest:");
1069 assert(msg != NULL);
1072 if (sha1ctx == NULL || sig == NULL || dig == NULL) {
1074 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
1078 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1079 (void) rpmDigestFinal(rpmDigestDup(sha1ctx),
1080 (void **)&SHA1, NULL, 1);
1081 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1083 if (SHA1 == NULL || strlen(SHA1) != strlen(sig) || strcmp(SHA1, sig)) {
1085 rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title,
1086 rpmSigString(res), sig, SHA1 ? SHA1 : "(nil)");
1089 rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), SHA1);
1098 * Verify RSA signature.
1099 * @param ts transaction set
1100 * @retval msg rbose success/failure text
1102 * @return RPMRC_OK on success
1105 verifyRSASignature(rpmts ts, char ** msg,
1108 rpm_constdata_t sig = rpmtsSig(ts);
1110 size_t siglen = rpmtsSiglen(ts);
1112 rpmSigTag sigtag = rpmtsSigtag(ts);
1113 pgpDig dig = rpmtsDig(ts);
1114 pgpDigParams sigp = rpmtsSignature(ts);
1116 rpmRC res = RPMRC_OK;
1119 const char *hdr, *signame = _("Unknown");;
1122 assert(msg != NULL);
1125 hdr = (dig != NULL && dig->hdrmd5ctx == md5ctx) ? _("Header ") : "";
1126 sigver = sigp !=NULL ? sigp->version : 0;
1128 if (md5ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
1134 /* Verify the desired signature match. */
1135 switch (sigp->pubkey_algo) {
1136 case PGPPUBKEYALGO_RSA:
1137 if (sigtag == RPMSIGTAG_PGP || sigtag == RPMSIGTAG_PGP5 || sigtag == RPMSIGTAG_RSA)
1144 /* Verify the desired hash match. */
1145 /* XXX Values from PKCS#1 v2.1 (aka RFC-3447) */
1146 switch (sigp->hash_algo) {
1147 case PGPHASHALGO_MD5:
1148 signame = "RSA/MD5";
1149 sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
1151 case PGPHASHALGO_SHA1:
1152 signame = "RSA/SHA1";
1153 sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
1155 case PGPHASHALGO_MD2:
1156 signame = "RSA/MD2";
1157 sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
1159 case PGPHASHALGO_SHA256:
1160 signame = "RSA/SHA256";
1161 sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
1163 case PGPHASHALGO_SHA384:
1164 signame = "RSA/SHA384";
1165 sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
1167 case PGPHASHALGO_SHA512:
1168 signame = "RSA/SHA512";
1169 sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
1171 /* fallthrough for unsupported / unknown types */
1172 case PGPHASHALGO_TIGER192:
1173 case PGPHASHALGO_HAVAL_5_160:
1174 case PGPHASHALGO_RIPEMD160:
1177 sigalg = SEC_OID_UNKNOWN;
1181 if (res != RPMRC_OK) {
1185 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1186 { DIGEST_CTX ctx = rpmDigestDup(md5ctx);
1188 if (sigp->hash != NULL)
1189 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1191 #ifdef NOTYET /* XXX not for binary/text signatures as in packages. */
1192 if (!(sigp->sigtype == PGPSIGTYPE_BINARY || sigp->sigtype == PGP_SIGTYPE_TEXT)) {
1193 size_t nb = dig->nbytes + sigp->hashlen;
1198 memcpy(trailer+2, &nb, sizeof(nb));
1199 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1203 xx = rpmDigestFinal(ctx, (void **)&dig->md5, &dig->md5len, 0);
1204 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), sigp->hashlen);
1205 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1207 /* Compare leading 16 bits of digest for quick check. */
1208 if (memcmp(dig->md5, sigp->signhash16, 2)) {
1212 digest.type = siBuffer;
1213 digest.data = dig->md5;
1214 digest.len = dig->md5len;
1217 /* Retrieve the matching public key. */
1218 res = rpmtsFindPubkey(ts);
1219 if (res != RPMRC_OK)
1222 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1223 if (VFY_VerifyDigest(&digest, dig->rsa, dig->rsasig, sigalg, NULL) == SECSuccess)
1227 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1231 char *signid = pgpHexStr(sigp->signid+4, sizeof(sigp->signid)-4);
1232 rasprintf(msg, _("%sV%d %s signature: %s, key ID %s\n"),
1233 hdr, sigver, signame, rpmSigString(res), signid);
1236 rasprintf(msg, _("%sV%d %s signature: %s\n"),
1237 hdr, sigver, signame, rpmSigString(res));
1243 * Verify DSA signature.
1244 * @param ts transaction set
1245 * @retval t verbose success/failure text
1247 * @return RPMRC_OK on success
1250 verifyDSASignature(rpmts ts, char ** msg,
1253 rpm_constdata_t sig = rpmtsSig(ts);
1255 size_t siglen = rpmtsSiglen(ts);
1257 rpmSigTag sigtag = rpmtsSigtag(ts);
1258 pgpDig dig = rpmtsDig(ts);
1259 pgpDigParams sigp = rpmtsSignature(ts);
1266 assert(msg != NULL);
1269 hdr = (dig != NULL && dig->hdrsha1ctx == sha1ctx) ? _("Header ") : "";
1270 sigver = sigp !=NULL ? sigp->version : 0;
1272 if (sha1ctx == NULL || sig == NULL || dig == NULL || sigp == NULL) {
1277 /* XXX sanity check on sigtag and signature agreement. */
1278 if (!((sigtag == RPMSIGTAG_GPG || sigtag == RPMSIGTAG_DSA)
1279 && sigp->pubkey_algo == PGPPUBKEYALGO_DSA
1280 && sigp->hash_algo == PGPHASHALGO_SHA1))
1286 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1287 { DIGEST_CTX ctx = rpmDigestDup(sha1ctx);
1289 if (sigp->hash != NULL)
1290 xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
1292 if (sigp->version == 4) {
1293 size_t nb = sigp->hashlen;
1294 uint8_t *trailer = xmalloc(2+sizeof(nb));
1296 trailer[0] = sigp->version;
1298 memcpy(trailer+2, &nb, sizeof(nb));
1299 xx = rpmDigestUpdate(ctx, trailer, sizeof(trailer));
1302 xx = rpmDigestFinal(ctx, (void **)&dig->sha1, &dig->sha1len, 0);
1303 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), sigp->hashlen);
1304 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1306 /* Compare leading 16 bits of digest for quick check. */
1307 if (memcmp(dig->sha1, sigp->signhash16, 2)) {
1311 digest.type = siBuffer;
1312 digest.data = dig->sha1;
1313 digest.len = dig->sha1len;
1316 /* Retrieve the matching public key. */
1317 res = rpmtsFindPubkey(ts);
1318 if (res != RPMRC_OK)
1321 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1322 if (VFY_VerifyDigest(&digest, dig->dsa, dig->dsasig,
1323 SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, NULL) == SECSuccess)
1327 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_SIGNATURE), 0);
1331 char *signid = pgpHexStr(sigp->signid+4, sizeof(sigp->signid)-4);
1332 rasprintf(msg, _("%sV%d DSA signature: %s, key ID %s\n"),
1333 hdr, sigver, rpmSigString(res), signid);
1336 rasprintf(msg, _("%sV%d DSA signature: %s\n"),
1337 hdr, sigver, rpmSigString(res));
1343 rpmVerifySignature(const rpmts ts, char ** result)
1345 rpm_constdata_t sig = rpmtsSig(ts);
1346 size_t siglen = rpmtsSiglen(ts);
1347 rpmSigTag sigtag = rpmtsSigtag(ts);
1348 pgpDig dig = rpmtsDig(ts);
1351 assert(result != NULL);
1353 if (sig == NULL || siglen <= 0 || dig == NULL) {
1354 rasprintf(result, _("Verify signature: BAD PARAMETERS\n"));
1355 return RPMRC_NOTFOUND;
1359 case RPMSIGTAG_SIZE:
1360 res = verifySizeSignature(ts, result);
1363 res = verifyMD5Signature(ts, result, dig->md5ctx);
1365 case RPMSIGTAG_SHA1:
1366 res = verifySHA1Signature(ts, result, dig->hdrsha1ctx);
1369 res = verifyRSASignature(ts, result, dig->hdrmd5ctx);
1371 case RPMSIGTAG_PGP5: /* XXX legacy */
1373 res = verifyRSASignature(ts, result,
1374 ((dig->signature.hash_algo == PGPHASHALGO_MD5)
1375 ? dig->md5ctx : dig->sha1ctx));
1378 res = verifyDSASignature(ts, result, dig->hdrsha1ctx);
1381 res = verifyDSASignature(ts, result, dig->sha1ctx);
1383 case RPMSIGTAG_LEMD5_1:
1384 case RPMSIGTAG_LEMD5_2:
1385 rasprintf(result, _("Broken MD5 digest: UNSUPPORTED\n"));
1386 res = RPMRC_NOTFOUND;
1389 rasprintf(result, _("Signature: UNKNOWN (%d)\n"), sigtag);
1390 res = RPMRC_NOTFOUND;