summaryrefslogtreecommitdiff
path: root/sign/rpmsignfiles.c
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2017-06-08 16:29:40 +0300
committerPanu Matilainen <pmatilai@redhat.com>2017-06-08 17:01:28 +0300
commit9e16032b0be115c73c45a324f7ff5b9f5e4720c4 (patch)
tree3b5bf39ca57971c3ebeb00d7bf250f35b694395e /sign/rpmsignfiles.c
parent5a76125050c2f389cdc1c3017dff5fec4aef7e57 (diff)
downloadrpm-9e16032b0be115c73c45a324f7ff5b9f5e4720c4.tar.gz
Move rpmsignfiles to librpmsign where it belongs
The signing library is separated from librpm and librpmbuild specifically so it can have more exotic dependencies than is desireable for librpm, ditto for plugin existence. However rpmSignFiles() being in librpm drags that libimaevm dependency to main rpm for no good reason at all. Move it where it belongs, does not actually affect functionality.
Diffstat (limited to 'sign/rpmsignfiles.c')
-rw-r--r--sign/rpmsignfiles.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/sign/rpmsignfiles.c b/sign/rpmsignfiles.c
new file mode 100644
index 000000000..1666befb1
--- /dev/null
+++ b/sign/rpmsignfiles.c
@@ -0,0 +1,140 @@
+/**
+ * Copyright (C) 2014 IBM Corporation
+ *
+ * Author: Fionnuala Gunter <fin@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 "sign/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",
+};
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+static char *signFile(const char *algo, const char *fdigest, int diglen,
+const char *key, char *keypass)
+{
+ char *fsignature;
+ unsigned char digest[diglen];
+ unsigned char signature[MAX_SIGNATURE_LENGTH];
+ int siglen;
+
+#ifndef WITH_IMAEVM
+ rpmlog(RPMLOG_ERR, _("missing libimaevm\n"));
+ return NULL;
+#endif
+
+ /* convert file digest hex to binary */
+ memset(digest, 0, diglen);
+ /* some entries don't have a digest - we return an empty signature */
+ if (strlen(fdigest) != diglen * 2)
+ return strdup("");
+
+ 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, keypass, 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,
+char *keypass)
+{
+ 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, keypass,
+ signature+1);
+ return siglen + 1;
+}
+
+rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
+{
+ 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) {
+ /* use default algorithm */
+ algo = PGPHASHALGO_MD5;
+ } else if (algo < 0 || algo >= ARRAY_SIZE(hash_algo_name)) {
+ rpmlog(RPMLOG_ERR, _("File digest algorithm id is invalid"));
+ 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, keypass);
+ headerPutUint32(h, RPMTAG_FILESIGNATURELENGTH, &siglen, 1);
+
+ headerGet(h, RPMTAG_FILEDIGESTS, &digests, HEADERGET_MINMEM);
+ while ((digest = rpmtdNextString(&digests))) {
+ signature = signFile(algoname, digest, diglen, key, keypass);
+ if (!signature) {
+ rpmlog(RPMLOG_ERR, _("signFile failed\n"));
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+ if (!headerPutString(h, RPMTAG_FILESIGNATURES, signature)) {
+ free(signature);
+ rpmlog(RPMLOG_ERR, _("headerPutString failed\n"));
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+ free(signature);
+ }
+
+exit:
+ rpmtdFreeData(&digests);
+ return rc;
+}