2 * Copyright (C) 2014 IBM Corporation
4 * Author: Fionnuala Gunter <fin@linux.vnet.ibm.com>
10 #include <rpm/rpmlog.h> /* rpmlog */
11 #include <rpm/rpmstring.h> /* rnibble */
12 #include <rpm/rpmpgp.h> /* rpmDigestLength */
13 #include "lib/header.h" /* HEADERGET_MINMEM */
14 #include "lib/rpmtypes.h" /* rpmRC */
16 #include "sign/rpmsignfiles.h"
18 #define MAX_SIGNATURE_LENGTH 1024
20 static const char *hash_algo_name[] = {
21 [PGPHASHALGO_MD5] = "md5",
22 [PGPHASHALGO_SHA1] = "sha1",
23 [PGPHASHALGO_RIPEMD160] = "rmd160",
24 [PGPHASHALGO_MD2] = "md2",
25 [PGPHASHALGO_TIGER192] = "tgr192",
26 [PGPHASHALGO_HAVAL_5_160] = "haval5160",
27 [PGPHASHALGO_SHA256] = "sha256",
28 [PGPHASHALGO_SHA384] = "sha384",
29 [PGPHASHALGO_SHA512] = "sha512",
30 [PGPHASHALGO_SHA224] = "sha224",
33 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
35 static char *signFile(const char *algo, const char *fdigest, int diglen,
36 const char *key, char *keypass)
39 unsigned char digest[diglen];
40 unsigned char signature[MAX_SIGNATURE_LENGTH];
43 /* convert file digest hex to binary */
44 memset(digest, 0, diglen);
45 /* some entries don't have a digest - we return an empty signature */
46 if (strlen(fdigest) != diglen * 2)
49 for (int i = 0; i < diglen; ++i, fdigest += 2)
50 digest[i] = (rnibble(fdigest[0]) << 4) | rnibble(fdigest[1]);
52 /* prepare file signature */
53 memset(signature, 0, MAX_SIGNATURE_LENGTH);
54 signature[0] = '\x03';
56 /* calculate file signature */
57 siglen = sign_hash(algo, digest, diglen, key, keypass, signature+1);
59 rpmlog(RPMLOG_ERR, _("sign_hash failed\n"));
63 /* convert file signature binary to hex */
64 fsignature = pgpHexStr(signature, siglen+1);
68 static uint32_t signatureLength(const char *algo, int diglen, const char *key,
71 unsigned char digest[diglen];
72 unsigned char signature[MAX_SIGNATURE_LENGTH];
74 memset(digest, 0, diglen);
75 memset(signature, 0, MAX_SIGNATURE_LENGTH);
76 signature[0] = '\x03';
78 uint32_t siglen = sign_hash(algo, digest, diglen, key, keypass,
83 rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
85 struct rpmtd_s digests;
94 algo = headerGetNumber(h, RPMTAG_FILEDIGESTALGO);
96 /* use default algorithm */
97 algo = PGPHASHALGO_MD5;
98 } else if (algo < 0 || algo >= ARRAY_SIZE(hash_algo_name)) {
99 rpmlog(RPMLOG_ERR, _("File digest algorithm id is invalid"));
103 diglen = rpmDigestLength(algo);
104 algoname = hash_algo_name[algo];
106 rpmlog(RPMLOG_ERR, _("hash_algo_name failed\n"));
110 headerDel(h, RPMTAG_FILESIGNATURELENGTH);
111 headerDel(h, RPMTAG_FILESIGNATURES);
112 siglen = signatureLength(algoname, diglen, key, keypass);
113 headerPutUint32(h, RPMTAG_FILESIGNATURELENGTH, &siglen, 1);
115 headerGet(h, RPMTAG_FILEDIGESTS, &digests, HEADERGET_MINMEM);
116 while ((digest = rpmtdNextString(&digests))) {
117 signature = signFile(algoname, digest, diglen, key, keypass);
119 rpmlog(RPMLOG_ERR, _("signFile failed\n"));
123 if (!headerPutString(h, RPMTAG_FILESIGNATURES, signature)) {
125 rpmlog(RPMLOG_ERR, _("headerPutString failed\n"));
133 rpmtdFreeData(&digests);