[Rpm-maint] [PATCH v9 12/13] Add support for passing the file signing key password

Fionnuala Gunter fionnuala.gunter at gmail.com
Tue Jul 21 17:00:46 UTC 2015


From: Mimi Zohar <zohar at us.ibm.com>

The option to provide a password for signing an RPM package was
recently removed in favor of using the underlying mechanisms.

Requiring a user to enter a password for each file being signed,
however, is tedious. This patch adds support for prompting the
user for the password.

Dependency on ima-evm-utils version > "0.9"

Changelog:
- update get_fskpass() based on Dmitry's comments
---
 lib/rpmsignfiles.c | 52 +++++++++++++++++++++++++++++++++++++++++++++-------
 lib/rpmsignfiles.h |  5 ++++-
 rpmsign.c          | 22 +++++++++++++++++++++-
 sign/rpmgensig.c   |  7 ++++++-
 4 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/lib/rpmsignfiles.c b/lib/rpmsignfiles.c
index 414983b..4336f8c 100644
--- a/lib/rpmsignfiles.c
+++ b/lib/rpmsignfiles.c
@@ -7,6 +7,8 @@
 #include "system.h"
 #include "imaevm.h"
 
+#include <termios.h>
+
 #include <rpm/rpmlog.h>		/* rpmlog */
 #include <rpm/rpmstring.h>	/* rnibble */
 #include <rpm/rpmpgp.h>		/* rpmDigestLength */
@@ -30,7 +32,41 @@ static const char *hash_algo_name[] = {
     [PGPHASHALGO_SHA224]       = "sha224",
 };
 
-static char *signFile(const char *algo, const char *fdigest, int diglen, const char *key)
+char *get_fskpass(void)
+{
+    struct termios flags, tmp_flags;
+    char *password, *pwd;
+    int passlen = 64;
+
+    password = malloc(passlen);
+    if (!password) {
+	perror("malloc");
+	return NULL;
+    }
+
+    tcgetattr(fileno(stdin), &flags);
+    tmp_flags = flags;
+    tmp_flags.c_lflag &= ~ECHO;
+    tmp_flags.c_lflag |= ECHONL;
+
+    if (tcsetattr(fileno(stdin), TCSANOW, &tmp_flags) != 0) {
+	perror("tcsetattr");
+	return NULL;
+    }
+
+    printf("PEM password: ");
+    pwd = fgets(password, passlen, stdin);
+    pwd[strlen(pwd) - 1] = '\0';  /* remove newline */
+
+    if (tcsetattr(fileno(stdin), TCSANOW, &flags) != 0) {
+	perror("tcsetattr");
+	return NULL;
+    }
+    return pwd;
+}
+
+static char *signFile(const char *algo, const char *fdigest, int diglen,
+const char *key, char *keypass)
 {
    char *fsignature;
    unsigned char digest[diglen];
@@ -52,7 +88,7 @@ static char *signFile(const char *algo, const char *fdigest, int diglen, const c
    signature[0] = '\x03';
 
    /* calculate file signature */
-   siglen = sign_hash(algo, digest, diglen, key, signature+1);
+   siglen = sign_hash(algo, digest, diglen, key, keypass, signature+1);
    if (siglen < 0) {
         rpmlog(RPMLOG_ERR, _("sign_hash failed\n"));
         return NULL;
@@ -63,7 +99,8 @@ static char *signFile(const char *algo, const char *fdigest, int diglen, const c
    return fsignature;
 }
 
-static uint32_t signatureLength(const char *algo, int diglen, const char *key)
+static uint32_t signatureLength(const char *algo, int diglen, const char *key,
+char *keypass)
 {
     unsigned char digest[diglen];
     unsigned char signature[MAX_SIGNATURE_LENGTH];
@@ -72,11 +109,12 @@ static uint32_t signatureLength(const char *algo, int diglen, const char *key)
     memset(signature, 0, MAX_SIGNATURE_LENGTH);
     signature[0] = '\x03';
 
-    uint32_t siglen = sign_hash(algo, digest, diglen, key, signature+1);
+    uint32_t siglen = sign_hash(algo, digest, diglen, key, keypass,
+				signature+1);
     return siglen + 1;
 }
 
-rpmRC rpmSignFiles(Header h, const char *key)
+rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
 {
     struct rpmtd_s digests;
     int algo;
@@ -102,12 +140,12 @@ rpmRC rpmSignFiles(Header h, const char *key)
 
     headerDel(h, RPMTAG_FILESIGNATURELENGTH);
     headerDel(h, RPMTAG_FILESIGNATURES);
-    siglen = signatureLength(algoname, diglen, key);
+    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);
+        signature = signFile(algoname, digest, diglen, key, keypass);
         if (!signature) {
             rpmlog(RPMLOG_ERR, _("signFile failed\n"));
             rc = RPMRC_FAIL;
diff --git a/lib/rpmsignfiles.h b/lib/rpmsignfiles.h
index 70a5b9f..52e2482 100644
--- a/lib/rpmsignfiles.h
+++ b/lib/rpmsignfiles.h
@@ -9,9 +9,12 @@ extern "C" {
  * Sign file digests in header and store the signatures in header
  * @param h		package header
  * @param key		signing key
+ * @param keypass	signing key password
  * @return		RPMRC_OK on success
  */
-rpmRC rpmSignFiles(Header h, const char *key);
+rpmRC rpmSignFiles(Header h, const char *key, char *keypass);
+
+char *get_fskpass(void); /* get file signing key password */
 
 #ifdef _cplusplus
 }
diff --git a/rpmsign.c b/rpmsign.c
index ce4198a..7f48d98 100644
--- a/rpmsign.c
+++ b/rpmsign.c
@@ -6,6 +6,7 @@
 #include <rpm/rpmcli.h>
 #include <rpm/rpmsign.h>
 #include "cliutils.h"
+#include "lib/rpmsignfiles.h"
 #include "debug.h"
 
 #if !defined(__GLIBC__) && !defined(__APPLE__)
@@ -20,8 +21,9 @@ enum modes {
 
 static int mode = 0;
 
-static int signfiles = 0;
+static int signfiles = 0, fskpass = 0;
 static char * fileSigningKey = NULL;
+static char * fileSigningKeyPassword = NULL;
 
 static struct poptOption signOptsTable[] = {
     { "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN,
@@ -35,6 +37,8 @@ static struct poptOption signOptsTable[] = {
     { "fskpath", '\0', POPT_ARG_STRING, &fileSigningKey, 0,
 	N_("use file signing key <key>"),
 	N_("<key>") },
+    { "fskpass", '\0', POPT_ARG_NONE, &fskpass, 0,
+	N_("prompt for file signing key password"), NULL},
     POPT_TABLEEND
 };
 
@@ -72,6 +76,22 @@ static int doSign(poptContext optCon)
 	    fprintf(stderr, _("You must set \"$$_file_signing_key\" in your macro file or on the command line with --fskpath\n"));
 	    goto exit;
 	}
+
+	if (fskpass) {
+#ifndef WITH_IMAEVM
+	    argerror(_("--fskpass may only be specified when signing files"));
+#else
+	    fileSigningKeyPassword = get_fskpass();
+#endif
+	}
+
+	addMacro(NULL, "_file_signing_key_password", NULL,
+	    fileSigningKeyPassword, RMIL_CMDLINE);
+	if (fileSigningKeyPassword) {
+	    memset(fileSigningKeyPassword, 0, strlen(fileSigningKeyPassword));
+	    free(fileSigningKeyPassword);
+	}
+
 	sig.signfiles = 1;
     }
 
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index bc50ee4..c312e39 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -553,6 +553,7 @@ static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
     FD_t ofd = NULL;
     char *trpm = NULL;
     const char *key;
+    char *keypass;
     char *SHA1 = NULL;
     uint8_t *MD5 = NULL;
     size_t sha1len;
@@ -571,7 +572,11 @@ static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
 
     key = rpmExpand("%{?_file_signing_key}", NULL);
 
-    rc = rpmSignFiles(*hdrp, key);
+    keypass = rpmExpand("%{_file_signing_key_password}", NULL);
+    if (rstreq(keypass, ""))
+	keypass = NULL;
+
+    rc = rpmSignFiles(*hdrp, key, keypass);
     if (rc != RPMRC_OK) {
 	goto exit;
     }
-- 
2.4.3



More information about the Rpm-maint mailing list