[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