Blob Blame History Raw
From 3669fecaba2858aeca44d1bfc265760611ea8834 Mon Sep 17 00:00:00 2001
From: Jes Sorensen <jsorensen@fb.com>
Date: Wed, 10 Jun 2020 12:30:54 -0400
Subject: [PATCH 32/33] rpmsign: Add argument to specify algorithm for fsverity
 signatures

The argument --verity-algo can be used to specify the algorithm for
the fsverity signatures. If nothing is specified, this will default to
sha256. The available algorithms depend on libfsverity, currently
sha256 and sha512 are supported.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
 doc/rpmsign.8        |  3 +++
 rpmsign.c            |  7 +++++++
 sign/rpmgensig.c     | 22 ++++++++++++++++++++--
 sign/rpmsignverity.c |  6 +++---
 sign/rpmsignverity.h |  2 +-
 5 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/doc/rpmsign.8 b/doc/rpmsign.8
index a212746fe..5165e39f9 100644
--- a/doc/rpmsign.8
+++ b/doc/rpmsign.8
@@ -55,6 +55,9 @@ Used with \fB--signfiles\fR, use file signing key \fIKey\fR.
 \fB--certpath \fICERT\fB\fR
 Used with \fB--signverity\fR, use file signing certificate \fICert\fR.
 .TP
+\fB--verityalgo \fIALG\fB\fR
+Used with \fB--signverity\fR, to specify the signing algorithm. sha256 and sha512 are supported, with sha256 being the default if this argument is not specified. This can also be specified with the macro %_verity_algorithm
+.TP
 \fB--signfiles\fR
 Sign package files. The macro \fB%_binary_filedigest_algorithm\fR must
 be set to a supported algorithm before building the package. The
diff --git a/rpmsign.c b/rpmsign.c
index e43811e9f..12299379c 100644
--- a/rpmsign.c
+++ b/rpmsign.c
@@ -25,6 +25,7 @@ static char * fileSigningKey = NULL;
 #endif
 #ifdef WITH_FSVERITY
 static char * fileSigningCert = NULL;
+static char * verityAlgorithm = NULL;
 #endif
 
 static struct rpmSignArgs sargs = {NULL, 0, 0};
@@ -52,6 +53,9 @@ static struct poptOption signOptsTable[] = {
     { "signverity", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR),
 	&sargs.signflags, RPMSIGN_FLAG_FSVERITY,
 	N_("generate fsverity signatures for package(s) files"), NULL},
+    { "verityalgo", '\0', POPT_ARG_STRING, &verityAlgorithm, 0,
+	N_("algorithm to use for verity signatures, default sha256"),
+	N_("<algorithm>") },
     { "certpath", '\0', POPT_ARG_STRING, &fileSigningCert, 0,
 	N_("use file signing cert <cert>"),
 	N_("<cert>") },
@@ -138,6 +142,9 @@ static int doSign(poptContext optCon, struct rpmSignArgs *sargs)
     if (fileSigningCert) {
 	rpmPushMacro(NULL, "_file_signing_cert", NULL, fileSigningCert, RMIL_GLOBAL);
     }
+    if (verityAlgorithm) {
+	rpmPushMacro(NULL, "_verity_algorithm", NULL, verityAlgorithm, RMIL_GLOBAL);
+    }
 #endif
 
     if (flags_sign_files(sargs->signflags)) {
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index 02cf0bc62..b3b02828a 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -8,6 +8,10 @@
 #include <sys/wait.h>
 #include <popt.h>
 #include <fcntl.h>
+#include <fcntl.h>
+#ifdef WITH_FSVERITY
+#include <libfsverity.h>
+#endif
 
 #include <rpm/rpmlib.h>			/* RPMSIGTAG & related */
 #include <rpm/rpmmacro.h>
@@ -458,23 +462,37 @@ static rpmRC includeFileSignatures(Header *sigp, Header *hdrp)
 static rpmRC includeVeritySignatures(FD_t fd, Header *sigp, Header *hdrp)
 {
 #ifdef WITH_FSVERITY
-    rpmRC rc;
+    rpmRC rc = RPMRC_OK;
     char *key = rpmExpand("%{?_file_signing_key}", NULL);
     char *keypass = rpmExpand("%{?_file_signing_key_password}", NULL);
     char *cert = rpmExpand("%{?_file_signing_cert}", NULL);
+    char *algorithm = rpmExpand("%{?_verity_algorithm}", NULL);
+    uint16_t algo = 0;
 
     if (rstreq(keypass, "")) {
 	free(keypass);
 	keypass = NULL;
     }
 
+    if (algorithm && strlen(algorithm) > 0) {
+	    algo = libfsverity_find_hash_alg_by_name(algorithm);
+	    rpmlog(RPMLOG_DEBUG, _("Searching for algorithm %s got %i\n"),
+		   algorithm, algo);
+	    if (!algo) {
+		    rpmlog(RPMLOG_ERR, _("Unsupported fsverity algorithm %s\n"),
+			   algorithm);
+		    rc = RPMRC_FAIL;
+		    goto out;
+	    }
+    }
     if (key && cert) {
-	rc = rpmSignVerity(fd, *sigp, *hdrp, key, keypass, cert);
+	    rc = rpmSignVerity(fd, *sigp, *hdrp, key, keypass, cert, algo);
     } else {
 	rpmlog(RPMLOG_ERR, _("fsverity signatures requires a key and a cert\n"));
 	rc = RPMRC_FAIL;
     }
 
+ out:
     free(keypass);
     free(key);
     free(cert);
diff --git a/sign/rpmsignverity.c b/sign/rpmsignverity.c
index 55096e732..e6c830cdc 100644
--- a/sign/rpmsignverity.c
+++ b/sign/rpmsignverity.c
@@ -95,7 +95,7 @@ static char *rpmVeritySignFile(rpmfi fi, size_t *sig_size, char *key,
 }
 
 rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
-		    char *keypass, char *cert)
+		    char *keypass, char *cert, uint16_t algo)
 {
     int rc;
     FD_t gzdi;
@@ -111,7 +111,6 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
     char **signatures = NULL;
     size_t sig_size;
     int nr_files, idx;
-    uint16_t algo;
     uint32_t algo32;
 
     Fseek(fd, 0, SEEK_SET);
@@ -156,7 +155,8 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
     nr_files = rpmfiFC(hfi);
     signatures = xcalloc(nr_files, sizeof(char *));
 
-    algo = FS_VERITY_HASH_ALG_SHA256;
+    if (!algo)
+	    algo = FS_VERITY_HASH_ALG_SHA256;
 
     rpmlog(RPMLOG_DEBUG, _("file count - header: %i, payload %i\n"),
 	   nr_files, rpmfiFC(fi));
diff --git a/sign/rpmsignverity.h b/sign/rpmsignverity.h
index 69bbaf7f7..d869e8d8e 100644
--- a/sign/rpmsignverity.h
+++ b/sign/rpmsignverity.h
@@ -27,7 +27,7 @@ extern "C" {
  */
 RPM_GNUC_INTERNAL
 rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
-		    char *keypass, char *cert);
+		    char *keypass, char *cert, uint16_t algo);
 
 #ifdef _cplusplus
 }
-- 
2.27.0