2 * \file lib/signature.c
10 #include <rpm/rpmtypes.h>
11 #include <rpm/rpmmacro.h> /* XXX for rpmExpand() */
12 #include <rpm/rpmstring.h>
13 #include <rpm/rpmfileutil.h>
14 #include <rpm/rpmlog.h>
15 #include <rpm/rpmkeyring.h>
17 #include "rpmio/digest.h"
18 #include "lib/rpmlead.h"
19 #include "lib/signature.h"
20 #include "lib/header_internal.h"
24 #if !defined(__GLIBC__) && !defined(__APPLE__)
25 char ** environ = NULL;
28 static int sighdrPut(Header h, rpmSigTag tag, rpmTagType type,
29 rpm_data_t p, rpm_count_t c)
37 return headerPut(h, &sigtd, HEADERPUT_DEFAULT);
40 int rpmLookupSignatureType(int action)
42 static int disabled = 0;
46 case RPMLOOKUPSIG_DISABLE:
49 case RPMLOOKUPSIG_ENABLE:
51 case RPMLOOKUPSIG_QUERY:
54 { char *name = rpmExpand("%{?_signature}", NULL);
55 if (!(name && *name != '\0'))
57 else if (!rstrcasecmp(name, "none"))
59 else if (!rstrcasecmp(name, "pgp"))
61 else if (!rstrcasecmp(name, "pgp5")) /* XXX legacy */
63 else if (!rstrcasecmp(name, "gpg"))
66 rc = -1; /* Invalid %_signature spec in macro file */
75 * @todo rpmio: use fdSize rather than fstat(2) to get file size.
76 * @param fd package file handle
77 * @param siglen signature header size
78 * @param pad signature padding
79 * @param datalen length of header+payload
80 * @return rpmRC return code
82 static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad, rpm_loff_t datalen)
85 int fdno = Fileno(fd);
87 if (fstat(fdno, &st) < 0)
91 "Expected size: %12" PRIu64 \
92 " = lead(%d)+sigs(%zd)+pad(%zd)+data(%" PRIu64 ")\n",
93 RPMLEAD_SIZE+siglen+pad+datalen,
94 RPMLEAD_SIZE, siglen, pad, datalen);
96 " Actual size: %12" PRIu64 "\n", (rpm_loff_t) st.st_size);
101 rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg)
111 struct indexEntry_s entry;
112 struct entryInfo_s info;
113 unsigned char * dataStart;
114 unsigned char * dataEnd = NULL;
116 rpmRC rc = RPMRC_FAIL; /* assume failure */
123 if (sig_type != RPMSIGTYPE_HEADERSIG)
126 memset(block, 0, sizeof(block));
127 if ((xx = timedRead(fd, (void *)block, sizeof(block))) != sizeof(block)) {
128 rasprintf(&buf, _("sigh size(%d): BAD, read returned %d\n"),
129 (int)sizeof(block), xx);
132 if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) {
133 rasprintf(&buf, _("sigh magic: BAD\n"));
136 il = ntohl(block[2]);
137 if (il < 0 || il > 32) {
139 _("sigh tags: BAD, no. of tags(%d) out of range\n"), il);
142 dl = ntohl(block[3]);
143 if (dl < 0 || dl > 8192) {
145 _("sigh data: BAD, no. of bytes(%d) out of range\n"), dl);
149 memset(&entry, 0, sizeof(entry));
150 memset(&info, 0, sizeof(info));
152 nb = (il * sizeof(struct entryInfo_s)) + dl;
153 ei = xmalloc(sizeof(il) + sizeof(dl) + nb);
156 pe = (entryInfo) &ei[2];
157 dataStart = (unsigned char *) (pe + il);
158 if ((xx = timedRead(fd, (void *)pe, nb)) != nb) {
160 _("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx);
164 /* Check (and convert) the 1st tag element. */
165 xx = headerVerifyInfo(1, dl, pe, &entry.info, 0);
167 rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
168 0, entry.info.tag, entry.info.type,
169 entry.info.offset, entry.info.count);
173 /* Is there an immutable header region tag? */
174 if (entry.info.tag == RPMTAG_HEADERSIGNATURES
175 && entry.info.type == RPM_BIN_TYPE
176 && entry.info.count == REGION_TAG_COUNT)
179 if (entry.info.offset >= dl) {
181 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
182 entry.info.tag, entry.info.type,
183 entry.info.offset, entry.info.count);
187 /* Is there an immutable header region tag trailer? */
188 dataEnd = dataStart + entry.info.offset;
189 (void) memcpy(&info, dataEnd, REGION_TAG_COUNT);
190 /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */
191 if (info.tag == htonl(RPMTAG_HEADERIMAGE)) {
192 rpmSigTag stag = htonl(RPMTAG_HEADERSIGNATURES);
194 memcpy(dataEnd, &stag, sizeof(stag));
196 dataEnd += REGION_TAG_COUNT;
198 xx = headerVerifyInfo(1, dl, &info, &entry.info, 1);
200 !((entry.info.tag == RPMTAG_HEADERSIGNATURES || entry.info.tag == RPMTAG_HEADERIMAGE)
201 && entry.info.type == RPM_BIN_TYPE
202 && entry.info.count == REGION_TAG_COUNT))
205 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
206 entry.info.tag, entry.info.type,
207 entry.info.offset, entry.info.count);
210 memset(&info, 0, sizeof(info));
212 /* Is the no. of tags in the region less than the total no. of tags? */
213 ril = entry.info.offset/sizeof(*pe);
214 if ((entry.info.offset % sizeof(*pe)) || ril > il) {
215 rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
220 /* Sanity check signature tags */
221 memset(&info, 0, sizeof(info));
222 for (i = 1; i < il; i++) {
223 xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0);
226 _("sigh tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
227 i, entry.info.tag, entry.info.type,
228 entry.info.offset, entry.info.count);
233 /* OK, blob looks sane, load the header. */
234 sigh = headerLoad(ei);
236 rasprintf(&buf, _("sigh load: BAD\n"));
240 { size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
241 size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */
243 struct rpmtd_s sizetag;
244 rpm_loff_t archSize = 0;
246 /* Position at beginning of header. */
247 if (pad && (trc = timedRead(fd, (void *)block, pad)) != pad) {
249 _("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc);
253 /* Print package component sizes. */
254 if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) {
255 rpm_loff_t *tsize = rpmtdGetUint64(&sizetag);
256 archSize = (tsize) ? *tsize : 0;
257 } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) {
258 rpm_off_t *tsize = rpmtdGetUint32(&sizetag);
259 archSize = (tsize) ? *tsize : 0;
261 rpmtdFreeData(&sizetag);
262 rc = printSize(fd, sigSize, pad, archSize);
263 if (rc != RPMRC_OK) {
265 _("sigh sigSize(%zd): BAD, fstat(2) failed\n"), sigSize);
269 ei = NULL; /* XXX will be freed with header */
272 if (sighp && sigh && rc == RPMRC_OK)
273 *sighp = headerLink(sigh);
274 sigh = headerFree(sigh);
286 int rpmWriteSignature(FD_t fd, Header sigh)
288 static uint8_t buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
292 rc = headerWrite(fd, sigh, HEADER_MAGIC_YES);
296 sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
297 pad = (8 - (sigSize % 8)) % 8;
299 if (Fwrite(buf, sizeof(buf[0]), pad, fd) != pad)
302 rpmlog(RPMLOG_DEBUG, "Signature: size(%d)+pad(%d)\n", sigSize, pad);
306 Header rpmNewSignature(void)
308 Header sigh = headerNew();
312 Header rpmFreeSignature(Header sigh)
314 return headerFree(sigh);
318 * Generate GPG signature(s) for a header+payload file.
319 * @param file header+payload file name
320 * @retval *sigTagp signature tag
321 * @retval *pktp signature packet(s)
322 * @retval *pktlenp signature packet(s) length
323 * @param passPhrase private key pass phrase
324 * @return 0 on success, 1 on failure
326 static int makeGPGSignature(const char * file, rpmSigTag * sigTagp,
327 uint8_t ** pktp, size_t * pktlenp,
328 const char * passPhrase)
330 char * sigfile = NULL;
338 pgpDigParams sigp = NULL;
339 int rc = 1; /* assume failure */
341 rasprintf(&sigfile, "%s.sig", file);
343 addMacro(NULL, "__plaintext_filename", NULL, file, -1);
344 addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
346 inpipe[0] = inpipe[1] = 0;
347 if (pipe(inpipe) < 0) {
348 rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
352 if (!(pid = fork())) {
353 const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
355 (void) dup2(inpipe[0], 3);
356 (void) close(inpipe[1]);
358 if (gpg_path && *gpg_path != '\0')
359 (void) setenv("GNUPGHOME", gpg_path, 1);
360 (void) setenv("LC_ALL", "C", 1);
362 unsetenv("MALLOC_CHECK_");
363 cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
364 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
366 rc = execve(av[0], av+1, environ);
368 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
373 delMacro(NULL, "__plaintext_filename");
374 delMacro(NULL, "__signature_filename");
376 fpipe = fdopen(inpipe[1], "w");
377 (void) close(inpipe[0]);
379 fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
380 (void) fclose(fpipe);
383 (void) waitpid(pid, &status, 0);
384 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
385 rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
389 if (stat(sigfile, &st)) {
390 /* GPG failed to write signature */
391 rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n"));
395 *pktlenp = st.st_size;
396 rpmlog(RPMLOG_DEBUG, "GPG sig size: %zd\n", *pktlenp);
397 *pktp = xmalloc(*pktlenp);
402 fd = Fopen(sigfile, "r.ufdio");
403 if (fd != NULL && !Ferror(fd)) {
404 rc = Fread(*pktp, sizeof(**pktp), *pktlenp, fd);
407 if (rc != *pktlenp) {
408 *pktp = _free(*pktp);
409 rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
414 rpmlog(RPMLOG_DEBUG, "Got %zd bytes of GPG sig\n", *pktlenp);
416 /* Parse the signature, change signature tag as appropriate. */
419 (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
420 sigp = &dig->signature;
424 /* XXX check MD5 hash too? */
425 if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
426 *sigTagp = RPMSIGTAG_PGP;
428 case RPMSIGTAG_PGP5: /* XXX legacy */
430 if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
431 *sigTagp = RPMSIGTAG_GPG;
434 /* XXX check MD5 hash too? */
435 if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
436 *sigTagp = RPMSIGTAG_RSA;
439 if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
440 *sigTagp = RPMSIGTAG_DSA;
446 dig = pgpFreeDig(dig);
450 (void) unlink(sigfile);
457 * Generate header only signature(s) from a header+payload file.
458 * @param sigh signature header
459 * @param file header+payload file name
460 * @param sigTag type of signature(s) to add
461 * @param passPhrase private key pass phrase
462 * @return 0 on success, -1 on failure
464 static int makeHDRSignature(Header sigh, const char * file, rpmSigTag sigTag,
465 const char * passPhrase)
469 uint8_t * pkt = NULL;
473 int ret = -1; /* assume failure. */
477 fd = Fopen(file, "r.fdio");
478 if (fd == NULL || Ferror(fd))
480 h = headerRead(fd, HEADER_MAGIC_YES);
483 (void) Fclose(fd); fd = NULL;
485 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
489 if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, HEADERGET_DEFAULT)
493 _("Immutable header region could not be read. "
494 "Corrupted package?\n"));
498 ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
499 (void) rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic));
500 (void) rpmDigestUpdate(ctx, utd.data, utd.count);
501 (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1);
508 if (!sighdrPut(sigh, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1))
514 fd = Fopen(file, "r.fdio");
515 if (fd == NULL || Ferror(fd))
517 h = headerRead(fd, HEADER_MAGIC_YES);
521 fd = rpmMkTempFile(NULL, &fn);
522 if (fd == NULL || Ferror(fd))
524 if (headerWrite(fd, h, HEADER_MAGIC_YES))
526 (void) Fclose(fd); fd = NULL;
527 if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
528 || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
545 if (fd != NULL) (void) Fclose(fd);
549 int rpmAddSignature(Header sigh, const char * file, rpmSigTag sigTag,
550 const char * passPhrase)
553 uint8_t * pkt = NULL;
555 int ret = -1; /* assume failure. */
558 case RPMSIGTAG_SIZE: {
560 if (stat(file, &st) != 0)
563 if (!sighdrPut(sigh, sigTag, RPM_INT32_TYPE, &size, 1))
567 case RPMSIGTAG_LONGSIZE: {
569 if (stat(file, &st) != 0)
572 if (!sighdrPut(sigh, sigTag, RPM_INT64_TYPE, &size, 1))
578 pkt = xcalloc(pktlen, sizeof(*pkt));
579 if (rpmDoDigest(PGPHASHALGO_MD5, file, 0, pkt, NULL)
580 || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
584 case RPMSIGTAG_PGP5: /* XXX legacy */
586 case RPMSIGTAG_GPG: {
587 rpmSigTag hdrtag = (sigTag == RPMSIGTAG_GPG) ?
588 RPMSIGTAG_DSA : RPMSIGTAG_RSA;
589 if (makeGPGSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
590 || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
592 /* XXX Piggyback a header-only DSA/RSA signature as well. */
593 ret = makeHDRSignature(sigh, file, hdrtag, passPhrase);
598 ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
608 static int checkPassPhrase(const char * passPhrase, const rpmSigTag sigTag)
610 int passPhrasePipe[2];
615 passPhrasePipe[0] = passPhrasePipe[1] = 0;
616 xx = pipe(passPhrasePipe);
617 if (!(pid = fork())) {
622 xx = close(STDIN_FILENO);
623 xx = close(STDOUT_FILENO);
624 xx = close(passPhrasePipe[1]);
625 if (! rpmIsVerbose())
626 xx = close(STDERR_FILENO);
627 if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
628 xx = dup2(fdno, STDIN_FILENO);
631 if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
632 xx = dup2(fdno, STDOUT_FILENO);
635 xx = dup2(passPhrasePipe[0], 3);
637 unsetenv("MALLOC_CHECK_");
640 case RPMSIGTAG_PGP5: /* XXX legacy */
644 { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
646 if (gpg_path && *gpg_path != '\0')
647 (void) setenv("GNUPGHOME", gpg_path, 1);
649 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
650 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
652 rc = execve(av[0], av+1, environ);
654 rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
657 default: /* This case should have been screened out long ago. */
658 rpmlog(RPMLOG_ERR, _("Invalid %%_signature spec in macro file\n"));
664 xx = close(passPhrasePipe[0]);
665 xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
666 xx = write(passPhrasePipe[1], "\n", 1);
667 xx = close(passPhrasePipe[1]);
669 (void) waitpid(pid, &status, 0);
671 return ((!WIFEXITED(status) || WEXITSTATUS(status)) ? 1 : 0);
674 char * rpmGetPassPhrase(const char * prompt, const rpmSigTag sigTag)
681 case RPMSIGTAG_PGP5: /* XXX legacy */
685 { char *name = rpmExpand("%{?_gpg_name}", NULL);
686 aok = (name && *name != '\0');
692 _("You must set \"%%_gpg_name\" in your macro file\n"));
695 /* Currently the calling function (rpm.c:main) is checking this and
696 * doing a better job. This section should never be accessed.
698 rpmlog(RPMLOG_ERR, _("Invalid %%_signature spec in macro file\n"));
703 pass = getpass( (prompt ? prompt : "") );
705 if (checkPassPhrase(pass, sigTag))
712 static const char * rpmSigString(rpmRC res)
716 case RPMRC_OK: str = "OK"; break;
717 case RPMRC_FAIL: str = "BAD"; break;
718 case RPMRC_NOKEY: str = "NOKEY"; break;
719 case RPMRC_NOTTRUSTED: str = "NOTRUSTED"; break;
721 case RPMRC_NOTFOUND: str = "UNKNOWN"; break;
727 verifyMD5Digest(rpmtd sigtd, DIGEST_CTX md5ctx, char **msg)
729 rpmRC res = RPMRC_FAIL; /* assume failure */
730 uint8_t * md5sum = NULL;
733 const char *title = _("MD5 digest:");
735 DIGEST_CTX ctx = rpmDigestDup(md5ctx);
737 if (ctx == NULL || sigtd->data == NULL) {
738 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
742 (void) rpmDigestFinal(ctx, (void **)&md5sum, &md5len, 0);
744 md5 = pgpHexStr(md5sum, md5len);
745 if (md5len != sigtd->count || memcmp(md5sum, sigtd->data, md5len)) {
746 char *hex = rpmtdFormat(sigtd, RPMTD_FORMAT_STRING, NULL);
747 rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title,
748 rpmSigString(res), hex, md5);
752 rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), md5);
757 md5sum = _free(md5sum);
762 * Verify header immutable region SHA1 digest.
763 * @retval msg verbose success/failure text
765 * @return RPMRC_OK on success
768 verifySHA1Digest(rpmtd sigtd, DIGEST_CTX sha1ctx, char **msg)
770 rpmRC res = RPMRC_FAIL; /* assume failure */
772 const char *title = _("Header SHA1 digest:");
773 const char *sig = sigtd->data;
775 DIGEST_CTX ctx = rpmDigestDup(sha1ctx);
777 if (ctx == NULL || sigtd->data == NULL) {
778 rasprintf(msg, "%s %s\n", title, rpmSigString(res));
782 (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1);
784 if (SHA1 == NULL || strlen(SHA1) != strlen(sig) || !rstreq(SHA1, sig)) {
785 rasprintf(msg, "%s %s Expected(%s) != (%s)\n", title,
786 rpmSigString(res), sig, SHA1 ? SHA1 : "(nil)");
789 rasprintf(msg, "%s %s (%s)\n", title, rpmSigString(res), SHA1);
798 * Verify DSA/RSA signature.
799 * @param keyring pubkey keyring
800 * @param dig OpenPGP container
801 * @param hashctx digest context
802 * @param isHdr header-only signature?
803 * @retval msg verbose success/failure text
804 * @return RPMRC_OK on success
807 verifySignature(rpmKeyring keyring, pgpDig dig, DIGEST_CTX hashctx, int isHdr,
810 pgpDigParams sigp = dig ? &dig->signature : NULL;
811 rpmRC res = RPMRC_FAIL; /* assume failure */
815 if (hashctx == NULL) {
819 /* Retrieve the matching public key and verify. */
820 res = rpmKeyringLookup(keyring, dig);
821 if (res == RPMRC_OK) {
822 res = pgpVerifySig(dig, hashctx);
826 sigid = pgpIdentItem(sigp);
827 rasprintf(msg, "%s%s: %s\n", isHdr ? _("Header ") : "", sigid,
834 rpmVerifySignature(rpmKeyring keyring, rpmtd sigtd, pgpDig dig, DIGEST_CTX ctx, char ** result)
836 rpmRC res = RPMRC_NOTFOUND;
839 if (sigtd->data == NULL || sigtd->count <= 0 || dig == NULL) {
840 rasprintf(&msg, _("Verify signature: BAD PARAMETERS\n"));
844 switch (sigtd->tag) {
846 res = verifyMD5Digest(sigtd, ctx, &msg);
849 res = verifySHA1Digest(sigtd, ctx, &msg);
853 res = verifySignature(keyring, dig, ctx, 1, &msg);
855 case RPMSIGTAG_PGP5: /* XXX legacy */
858 res = verifySignature(keyring, dig, ctx, 0, &msg);
861 rasprintf(&msg, _("Signature: UNKNOWN (%d)\n"), sigtd->tag);