[Rpm-maint] [PATCH v7 09/11] Add file signature support to package signing
Fionnuala Gunter
fionnuala.gunter at gmail.com
Tue Jul 21 19:56:19 UTC 2015
On Tue, Jul 21, 2015 at 3:18 AM, Lubos Kardos <lkardos at redhat.com> wrote:
>
> ----- Original Message -----
> > From: "Fionnuala Gunter" <fionnuala.gunter at gmail.com>
> > To: rpm-maint at lists.rpm.org
> > Cc: ffesti at redhat.org, zohar at linux.vnet.ibm.com, lkardos at redhat.com,
> "fin gunter" <fin.gunter at hypori.com>,
> > fin at linux.vnet.ibm.com
> > Sent: Tuesday, July 21, 2015 12:11:25 AM
> > Subject: [PATCH v7 09/11] Add file signature support to package signing
> >
> > From: "fin at linux.vnet.ibm.com" <fin at linux.vnet.ibm.com>
> >
> > This patch modifies rpmSign to include file signatures in the header.
> > Since the header is altered, the package digest and package+archive
> > digest need to be recalculated and updated in the signature header.
> > Defer resigning the header digests to replaceSignature().
> >
> > Changelog:
> > - removed extraneous semicolon - Mimi
> > - Update signature header digests only if necessary - Mimi
> > - rename headerSize to more accurate name sigTargetSize - Fin
> Maybe I should have been more clear. Renaming the variable is not enough.
> It
> still contains just header size but it should contain header size + size of
> compressed payload. Have a look at inline comments.
>
I don't think that's right. According to rpm man page, the SHA1 digest is
for the immutable header region, and the MD5 digest is for the combined
header and payload.
>
> Now I also noticed that you don't need to go through the same data twice.
> The first time to calculate SHA1 and the second time to calculate MD5. You
> can calculate both digest at the same time. Have a look at inline comments.
>
You are right about combining the MD5 calculation with SHA1, that can be
simplified.
>
> > - deallocate sigp before it's overriden - Fin
> > - fix dependency on ima - Fin
> > - replace utd parameter with a local variable - Mimi
> > ---
> > lib/rpmsignfiles.c | 2 +-
> > sign/rpmgensig.c | 185
> > +++++++++++++++++++++++++++++++++++++++++++++++++++--
> > 2 files changed, 180 insertions(+), 7 deletions(-)
> >
> > diff --git a/lib/rpmsignfiles.c b/lib/rpmsignfiles.c
> > index 376f47e..414983b 100644
> > --- a/lib/rpmsignfiles.c
> > +++ b/lib/rpmsignfiles.c
> > @@ -37,7 +37,7 @@ static char *signFile(const char *algo, const char
> > *fdigest, int diglen, const c
> > unsigned char signature[MAX_SIGNATURE_LENGTH];
> > int siglen;
> >
> > -#ifndef IMAEVM
> > +#ifndef WITH_IMAEVM
> > rpmlog(RPMLOG_ERR, _("missing libimaevm\n"));
> > return NULL;
> > #endif
> > diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
> > index b0bed44..d5557dc 100644
> > --- a/sign/rpmgensig.c
> > +++ b/sign/rpmgensig.c
> > @@ -17,9 +17,11 @@
> > #include <rpm/rpmfileutil.h> /* rpmMkTemp() */
> > #include <rpm/rpmlog.h>
> > #include <rpm/rpmstring.h>
> > +#include <rpmio/rpmio_internal.h>
> >
> > #include "lib/rpmlead.h"
> > #include "lib/signature.h"
> > +#include "lib/rpmsignfiles.h"
> >
> > #include "debug.h"
> >
> > @@ -471,9 +473,10 @@ static int replaceSignature(Header sigh, sigTarget
> > sigt1, sigTarget sigt2)
> > return rc;
> > }
> >
> > -static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag, rpmtd
> utd)
> > +static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag)
> > {
> > - struct rpmtd_s copytd;
> > + struct rpmtd_s copytd, td;
> > + rpmtd utd = &td;
> > Header nh;
> > Header oh;
> > HeaderIterator hi;
> > @@ -498,13 +501,179 @@ static void unloadImmutableRegion(Header *hdrp,
> > rpmTagVal tag, rpmtd utd)
> > }
> > }
> >
> > +static rpmRC replaceSigDigests(FD_t fd, const char *rpm, Header *sigp,
> > + off_t sigStart, off_t sigTargetSize,
> > + char *SHA1, uint8_t *MD5)
> > +{
> > + off_t archiveSize;
> > + rpmRC rc = RPMRC_OK;
> > +
> > + if (Fseek(fd, sigStart, SEEK_SET) < 0) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> > + rpm, Fstrerror(fd));
> > + goto exit;
> > + }
> > +
> > + /* Get payload size from signature tag */
> > + archiveSize = headerGetNumber(*sigp, RPMSIGTAG_PAYLOADSIZE);
> > + if (!archiveSize) {
> > + archiveSize = headerGetNumber(*sigp, RPMSIGTAG_LONGARCHIVESIZE);
> > + }
> > +
> > + /* Replace old digests in sigh */
> > + rc = rpmGenerateSignature(SHA1, MD5, sigTargetSize, archiveSize,
> fd);
> > + if (rc != RPMRC_OK) {
> > + rpmlog(RPMLOG_ERR, _("generateSignature failed\n"));
> > + goto exit;
> > + }
> > +
> > + if (Fseek(fd, sigStart, SEEK_SET) < 0) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> > + rpm, Fstrerror(fd));
> > + goto exit;
> > + }
> > +
> > + headerFree(*sigp);
> > + rc = rpmReadSignature(fd, sigp, RPMSIGTYPE_HEADERSIG, NULL);
> > + if (rc != RPMRC_OK) {
> > + rpmlog(RPMLOG_ERR, _("rpmReadSignature failed\n"));
> > + goto exit;
> > + }
> > +
> > +exit:
> > + return rc;
> > +}
> > +
> > +static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
> > + Header *sigp, Header *hdrp,
> > + off_t sigStart, off_t headerStart)
> > +{
> > + FD_t ofd = NULL;
> > + char *trpm = NULL;
> > + const char *key;
> > + char *SHA1 = NULL;
> > + uint8_t *MD5 = NULL;
> > + unsigned char buf[32*BUFSIZ];
> > + size_t sha1len;
> > + size_t md5len;
> > + off_t sigTargetSize;
> > + rpmRC rc = RPMRC_OK;
> > + struct rpmtd_s osigtd;
> > + char *o_sha1 = NULL;
> > + uint8_t o_md5[16];
> > +
> > +#ifndef WITH_IMAEVM
> > + rpmlog(RPMLOG_ERR, _("missing libimaevm\n"));
> > + return RPMRC_FAIL;
> > +#endif
> > + unloadImmutableRegion(hdrp, RPMTAG_HEADERIMMUTABLE);
> > +
> > + key = rpmExpand("%{?_file_signing_key}", NULL);
> > +
> > + rc = rpmSignFiles(*hdrp, key);
> > + if (rc != RPMRC_OK) {
> > + goto exit;
> > + }
> > +
> > + *hdrp = headerReload(*hdrp, RPMTAG_HEADERIMMUTABLE);
> > + if (*hdrp == NULL) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("headerReload failed\n"));
> > + goto exit;
> > + }
> > +
> > + ofd = rpmMkTempFile(NULL, &trpm);
> > + if (ofd == NULL || Ferror(ofd)) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
> > + goto exit;
> > + }
> > +
> > + /* Copy archive to temp file */
> > + if (copyFile(&fd, rpm, &ofd, trpm)) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("copyFile failed\n"));
> > + goto exit;
> > + }
> > +
> > + if (Fseek(fd, headerStart, SEEK_SET) < 0) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> > + rpm, Fstrerror(fd));
> > + goto exit;
> > + }
> > +
> //Start calculate also MD5
> fdInitDigest(fd, PGPHASHALGO_MD5, 0);
>
> > + /* Write header to rpm and recalculate SHA1 */
> > + fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
> > + rc = headerWrite(fd, *hdrp, HEADER_MAGIC_YES);
> > + if (rc != RPMRC_OK) {
> > + rpmlog(RPMLOG_ERR, _("headerWrite failed\n"));
> > + goto exit;
> > + }
> > + fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, &sha1len, 1);
> > + sigTargetSize = Ftell(fd) - headerStart;
> //This has to be moved below code for writing archive to
> //contain size of archive too.
>
> > +
> > + /* Copy archive from temp file */
> > + if (Fseek(ofd, 0, SEEK_SET) < 0) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> > + rpm, Fstrerror(fd));
> > + goto exit;
> > + }
> > + if (copyFile(&ofd, trpm, &fd, rpm)) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("copyFile failed\n"));
> > + goto exit;
> > + }
> > + unlink(trpm);
> //Here is the end of header + archive section
> sigTargetSize = Ftell(fd) - headerStart
> //Also end of calculating MD5
> fdInitDigest(fd, PGPHASHALGO_MD5, 0);
>
> > +
> //Following recalculation of MD5 is not needed.
> > + /* Recalculate MD5 digest of header+archive */
> > + if (Fseek(fd, headerStart, SEEK_SET) < 0) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> > + rpm, Fstrerror(fd));
> > + goto exit;
> > + }
> > + fdInitDigest(fd, PGPHASHALGO_MD5, 0);
> > +
> > + while (Fread(buf, sizeof(buf[0]), sizeof(buf), fd) > 0)
> > + ;
> > + if (Ferror(fd)) {
> > + rc = RPMRC_FAIL;
> > + rpmlog(RPMLOG_ERR, _("Fread failed in file %s: %s\n"),
> > + rpm, Fstrerror(fd));
> > + goto exit;
> > + }
> > + fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&MD5, &md5len, 0);
> > +
> > + if (headerGet(*sigp, RPMSIGTAG_MD5, &osigtd, HEADERGET_DEFAULT))
> > + memcpy(o_md5, osigtd.data, 16);
> > +
> > + if (headerGet(*sigp, RPMSIGTAG_SHA1, &osigtd, HEADERGET_DEFAULT))
> > + o_sha1 = xstrdup(osigtd.data);
> > +
> > + if (memcmp(MD5, o_md5, md5len) == 0 && strcmp(SHA1, o_sha1) == 0)
> > + rpmlog(RPMLOG_WARNING,
> > + _("%s already contains identical file signatures\n"),
> > + rpm);
> > + else
> > + replaceSigDigests(fd, rpm, sigp, sigStart, sigTargetSize, SHA1,
> MD5);
> > +
> > +exit:
> > +if (ofd) (void) closeFile(&ofd);
> > + return rc;
> > +}
> > +
> > /** \ingroup rpmcli
> > * Create/modify elements in signature header.
> > * @param rpm path to package
> > * @param deleting adding or deleting signature?
> > + * @param signfiles sign files if non-zero
> > * @return 0 on success, -1 on error
> > */
> > -static int rpmSign(const char *rpm, int deleting)
> > +static int rpmSign(const char *rpm, int deleting, int signfiles)
> > {
> > FD_t fd = NULL;
> > FD_t ofd = NULL;
> > @@ -555,7 +724,11 @@ static int rpmSign(const char *rpm, int deleting)
> > goto exit;
> > }
> >
> > - unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES, &utd);
> > + if (signfiles) {
> > + includeFileSignatures(fd, rpm, &sigh, &h, sigStart, headerStart);
> > + }
> > +
> > + unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES);
> > origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
> >
> > if (deleting) { /* Nuke all the signature tags. */
> > @@ -704,7 +877,7 @@ int rpmPkgSign(const char *path, const struct
> rpmSignArgs
> > * args)
> > }
> > }
> >
> > - rc = rpmSign(path, 0);
> > + rc = rpmSign(path, 0, args->signfiles);
> >
> > if (args) {
> > if (args->hashalgo) {
> > @@ -720,5 +893,5 @@ int rpmPkgSign(const char *path, const struct
> rpmSignArgs
> > * args)
> >
> > int rpmPkgDelSign(const char *path)
> > {
> > - return rpmSign(path, 1);
> > + return rpmSign(path, 1, 0);
> > }
> > --
> > 2.4.3
> >
> >
>
> Lubos
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rpm.org/pipermail/rpm-maint/attachments/20150721/a4cd2ed1/attachment-0001.html>
More information about the Rpm-maint
mailing list