[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