[Rpm-ecosystem] [PATCH v6 09/11] Sign file digests and store signatures in header

Lubos Kardos lkardos at redhat.com
Thu Jul 16 14:57:16 UTC 2015


Impossible to build if "--with-imaevm" option is not set:
lib/.libs/librpm.so: undefined reference to `sign_hash'
collect2: error: ld returned 1 exit status


----- Original Message -----
> From: "Mimi Zohar" <zohar at linux.vnet.ibm.com>
> To: rpm-ecosystem at lists.rpm.org
> Cc: fin at linux.vnet.ibm.com, "Fionnuala Gunter" <fionnuala.gunter at gmail.com>
> Sent: Monday, July 6, 2015 8:52:23 PM
> Subject: [Rpm-ecosystem] [PATCH v6 09/11] Sign file digests and store	signatures in header
> 
> From: "fin at linux.vnet.ibm.com" <fin at linux.vnet.ibm.com>
> 
> This patch introduces rpmSignFiles, which extracts file digests from
> the provided header and signs them using libimaevm and the provided key.
> The file signatures are stored in the header as hex strings under the
> tag RPM_FILESIGNATURES.
> 
> Changelog:
> - fix signatureLength() - Mimi
> - remove existing file signatures and the file signature length, before
> adding new file signatures. - Mimi
> ---
>  lib/Makefile.am    |   3 +-
>  lib/rpmsignfiles.c | 126
>  +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/rpmsignfiles.h |  20 +++++++++
>  3 files changed, 148 insertions(+), 1 deletion(-)
>  create mode 100644 lib/rpmsignfiles.c
>  create mode 100644 lib/rpmsignfiles.h
> 
> diff --git a/lib/Makefile.am b/lib/Makefile.am
> index 57de01e..ffb5ea1 100644
> --- a/lib/Makefile.am
> +++ b/lib/Makefile.am
> @@ -38,7 +38,8 @@ librpm_la_SOURCES = \
>  	verify.c rpmlock.c rpmlock.h misc.h relocation.c \
>  	rpmscript.h rpmscript.c legacy.c \
>  	rpmchroot.c rpmchroot.h \
> -	rpmplugins.c rpmplugins.h rpmplugin.h rpmug.c rpmug.h
> +	rpmplugins.c rpmplugins.h rpmplugin.h rpmug.c rpmug.h \
> +	rpmsignfiles.c rpmsignfiles.h
>  
>  librpm_la_LDFLAGS = -version-info $(rpm_version_info)
>  
> diff --git a/lib/rpmsignfiles.c b/lib/rpmsignfiles.c
> new file mode 100644
> index 0000000..376f47e
> --- /dev/null
> +++ b/lib/rpmsignfiles.c
> @@ -0,0 +1,126 @@
> +/**
> + * Copyright (C) 2014 IBM Corporation
> + *
> + * Author: Fionnuala Gunter <fin at linux.vnet.ibm.com>
> + */
> +
> +#include "system.h"
> +#include "imaevm.h"
> +
> +#include <rpm/rpmlog.h>		/* rpmlog */
> +#include <rpm/rpmstring.h>	/* rnibble */
> +#include <rpm/rpmpgp.h>		/* rpmDigestLength */
> +#include "lib/header.h"		/* HEADERGET_MINMEM */
> +#include "lib/rpmtypes.h"	/* rpmRC */
> +
> +#include "lib/rpmsignfiles.h"
> +
> +#define MAX_SIGNATURE_LENGTH 1024
> +
> +static const char *hash_algo_name[] = {
> +    [PGPHASHALGO_MD5]          = "md5",
> +    [PGPHASHALGO_SHA1]         = "sha1",
> +    [PGPHASHALGO_RIPEMD160]    = "rmd160",
> +    [PGPHASHALGO_MD2]          = "md2",
> +    [PGPHASHALGO_TIGER192]     = "tgr192",
> +    [PGPHASHALGO_HAVAL_5_160]  = "haval5160",
> +    [PGPHASHALGO_SHA256]       = "sha256",
> +    [PGPHASHALGO_SHA384]       = "sha384",
> +    [PGPHASHALGO_SHA512]       = "sha512",
> +    [PGPHASHALGO_SHA224]       = "sha224",
> +};
> +
> +static char *signFile(const char *algo, const char *fdigest, int diglen,
> const char *key)
> +{
> +   char *fsignature;
> +   unsigned char digest[diglen];
> +   unsigned char signature[MAX_SIGNATURE_LENGTH];
> +   int siglen;
> +
> +#ifndef IMAEVM
> +    rpmlog(RPMLOG_ERR, _("missing libimaevm\n"));
> +    return NULL;
> +#endif
> +
> +   /* convert file digest hex to binary */
> +   memset(digest, 0, diglen);
> +   for (int i = 0; i < diglen; ++i, fdigest += 2)
> +        digest[i] = (rnibble(fdigest[0]) << 4) | rnibble(fdigest[1]);
> +
> +   /* prepare file signature */
> +   memset(signature, 0, MAX_SIGNATURE_LENGTH);
> +   signature[0] = '\x03';
> +
> +   /* calculate file signature */
> +   siglen = sign_hash(algo, digest, diglen, key, signature+1);
> +   if (siglen < 0) {
> +        rpmlog(RPMLOG_ERR, _("sign_hash failed\n"));
> +        return NULL;
> +   }
> +
> +   /* convert file signature binary to hex */
> +   fsignature = pgpHexStr(signature, siglen+1);
> +   return fsignature;
> +}
> +
> +static uint32_t signatureLength(const char *algo, int diglen, const char
> *key)
> +{
> +    unsigned char digest[diglen];
> +    unsigned char signature[MAX_SIGNATURE_LENGTH];
> +
> +    memset(digest, 0, diglen);
> +    memset(signature, 0, MAX_SIGNATURE_LENGTH);
> +    signature[0] = '\x03';
> +
> +    uint32_t siglen = sign_hash(algo, digest, diglen, key, signature+1);
Is the key encrypted? If the key is encrypted then how user can enter passphrase?

> +    return siglen + 1;
> +}
> +
> +rpmRC rpmSignFiles(Header h, const char *key)
> +{
> +    struct rpmtd_s digests;
> +    int algo;
> +    int diglen;
> +    uint32_t siglen;
> +    const char *algoname;
> +    const char *digest;
> +    char *signature;
> +    rpmRC rc = RPMRC_OK;
> +
> +    algo = headerGetNumber(h, RPMTAG_FILEDIGESTALGO);
> +    if (!algo) {
> +	rpmlog(RPMLOG_ERR, _("missing RPMTAG_FILEDIGESTALGO\n"));
> +	return RPMRC_FAIL;
> +    }
> +
> +    diglen = rpmDigestLength(algo);
> +    algoname = hash_algo_name[algo];
> +    if (!algoname) {
> +	rpmlog(RPMLOG_ERR, _("hash_algo_name failed\n"));
> +	return RPMRC_FAIL;
> +    }
> +
> +    headerDel(h, RPMTAG_FILESIGNATURELENGTH);
> +    headerDel(h, RPMTAG_FILESIGNATURES);
> +    siglen = signatureLength(algoname, diglen, key);
> +    headerPutUint32(h, RPMTAG_FILESIGNATURELENGTH, &siglen, 1);
> +
> +    headerGet(h, RPMTAG_FILEDIGESTS, &digests, HEADERGET_MINMEM);
> +    while ((digest = rpmtdNextString(&digests))) {
> +        signature = signFile(algoname, digest, diglen, key);
> +        if (!signature) {
> +            rpmlog(RPMLOG_ERR, _("signFile failed\n"));
> +            rc = RPMRC_FAIL;
> +	    goto exit;
> +        }
> +        if (!headerPutString(h, RPMTAG_FILESIGNATURES, signature)) {
> +            rpmlog(RPMLOG_ERR, _("headerPutString failed\n"));
> +            rc = RPMRC_FAIL;
> +	    goto exit;
> +        }
> +    }
> +
> +exit:
> +    rpmtdFreeData(&digests);
> +    return rc;
> +}
> diff --git a/lib/rpmsignfiles.h b/lib/rpmsignfiles.h
> new file mode 100644
> index 0000000..70a5b9f
> --- /dev/null
> +++ b/lib/rpmsignfiles.h
> @@ -0,0 +1,20 @@
> +#ifndef H_RPMSIGNFILES
> +#define H_RPMSIGNFILES
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Sign file digests in header and store the signatures in header
> + * @param h		package header
> + * @param key		signing key
> + * @return		RPMRC_OK on success
> + */
> +rpmRC rpmSignFiles(Header h, const char *key);
> +
> +#ifdef _cplusplus
> +}
> +#endif
> +
> +#endif /* H_RPMSIGNFILES */
> --
> 2.1.0
> 
> _______________________________________________
> Rpm-ecosystem mailing list
> Rpm-ecosystem at lists.rpm.org
> http://lists.rpm.org/mailman/listinfo/rpm-ecosystem
> 

Lubos


More information about the Rpm-ecosystem mailing list