Blob Blame History Raw
From e339fdbbd0b81dc1fcdc2032e861b8a5fa6e062d Mon Sep 17 00:00:00 2001
From: Jes Sorensen <jsorensen@fb.com>
Date: Mon, 20 Apr 2020 13:40:26 -0400
Subject: [PATCH 26/33] fsverity - add tag for fsverity algorithm

The default algorith is SHA256, but fsverity allows for other
algorithms, so add a tag to handle this.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
 lib/package.c        |  1 +
 lib/rpmfi.c          |  2 ++
 lib/rpmtag.h         |  2 ++
 sign/rpmsignverity.c | 32 ++++++++++++++++++++++++++++----
 4 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/lib/package.c b/lib/package.c
index c6108f686..3c761d365 100644
--- a/lib/package.c
+++ b/lib/package.c
@@ -46,6 +46,7 @@ struct taglate_s {
     { RPMSIGTAG_FILESIGNATURES, RPMTAG_FILESIGNATURES, 0, 1 },
     { RPMSIGTAG_FILESIGNATURELENGTH, RPMTAG_FILESIGNATURELENGTH, 1, 1 },
     { RPMSIGTAG_VERITYSIGNATURES, RPMTAG_VERITYSIGNATURES, 0, 0 },
+    { RPMSIGTAG_VERITYSIGNATUREALGO, RPMTAG_VERITYSIGNATUREALGO, 1, 0 },
     { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1, 0 },
     { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1, 0 },
     { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0, 0 },
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index 5fdbe02a2..70f05f509 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -118,6 +118,7 @@ struct rpmfiles_s {
     int digestalgo;		/*!< File digest algorithm */
     uint32_t *signatureoffs;	/*!< File signature offsets */
     int veritysiglength;	/*!< Verity signature length */
+    uint16_t verityalgo;	/*!< Verity algorithm */
     unsigned char * digests;	/*!< File digests in binary. */
     unsigned char * signatures; /*!< File signatures in binary. */
     unsigned char * veritysigs; /*!< Verity signatures in binary. */
@@ -1667,6 +1668,7 @@ static int rpmfilesPopulate(rpmfiles fi, Header h, rpmfiFlags flags)
 
     fi->veritysigs = NULL;
     if (!(flags & RPMFI_NOVERITYSIGNATURES)) {
+	fi->verityalgo = headerGetNumber(h, RPMTAG_VERITYSIGNATUREALGO);
 	fi->veritysigs = base2bin(h, RPMTAG_VERITYSIGNATURES,
 				  totalfc, &fi->veritysiglength);
     }
diff --git a/lib/rpmtag.h b/lib/rpmtag.h
index 478457ecb..8d1efcc79 100644
--- a/lib/rpmtag.h
+++ b/lib/rpmtag.h
@@ -68,6 +68,7 @@ typedef enum rpmTag_e {
     /* RPMTAG_SIG_BASE+18 reserved for RPMSIGTAG_FILESIGNATURES */
     /* RPMTAG_SIG_BASE+19 reserved for RPMSIGTAG_FILESIGNATURELENGTH */
     RPMTAG_VERITYSIGNATURES	= RPMTAG_SIG_BASE+20,	/* s[] */
+    RPMTAG_VERITYSIGNATUREALGO	= RPMTAG_SIG_BASE+21,	/* i */
 
     RPMTAG_NAME  		= 1000,	/* s */
 #define	RPMTAG_N	RPMTAG_NAME	/* s */
@@ -431,6 +432,7 @@ typedef enum rpmSigTag_e {
     RPMSIGTAG_FILESIGNATURES		= RPMTAG_SIG_BASE + 18,
     RPMSIGTAG_FILESIGNATURELENGTH	= RPMTAG_SIG_BASE + 19,
     RPMSIGTAG_VERITYSIGNATURES		= RPMTAG_VERITYSIGNATURES,
+    RPMSIGTAG_VERITYSIGNATUREALGO	= RPMTAG_VERITYSIGNATUREALGO,
 } rpmSigTag;
 
 
diff --git a/sign/rpmsignverity.c b/sign/rpmsignverity.c
index 445e1197c..55096e732 100644
--- a/sign/rpmsignverity.c
+++ b/sign/rpmsignverity.c
@@ -35,7 +35,7 @@ static int rpmVerityRead(void *opaque, void *buf, size_t size)
 }
 
 static char *rpmVeritySignFile(rpmfi fi, size_t *sig_size, char *key,
-			       char *keypass, char *cert)
+			       char *keypass, char *cert, uint16_t algo)
 {
     struct libfsverity_merkle_tree_params params;
     struct libfsverity_signature_params sig_params;
@@ -52,7 +52,7 @@ static char *rpmVeritySignFile(rpmfi fi, size_t *sig_size, char *key,
 
     memset(&params, 0, sizeof(struct libfsverity_merkle_tree_params));
     params.version = 1;
-    params.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
+    params.hash_algorithm = algo;
     params.block_size = RPM_FSVERITY_BLKSZ;
     params.salt_size = 0 /* salt_size */;
     params.salt = NULL /* salt */;
@@ -111,6 +111,8 @@ 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);
     rpmtsSetVSFlags(ts, RPMVSF_MASK_NODIGESTS | RPMVSF_MASK_NOSIGNATURES |
@@ -142,6 +144,7 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
      * Should this be sigh from the cloned fd or the sigh we received?
      */
     headerDel(sigh, RPMSIGTAG_VERITYSIGNATURES);
+    headerDel(sigh, RPMSIGTAG_VERITYSIGNATUREALGO);
 
     /*
      * The payload doesn't include special files, like ghost files, and
@@ -153,20 +156,24 @@ 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;
+
     rpmlog(RPMLOG_DEBUG, _("file count - header: %i, payload %i\n"),
 	   nr_files, rpmfiFC(fi));
 
     while (rpmfiNext(fi) >= 0) {
 	idx = rpmfiFX(fi);
 
-	signatures[idx] = rpmVeritySignFile(fi, &sig_size, key, keypass, cert);
+	signatures[idx] = rpmVeritySignFile(fi, &sig_size, key, keypass, cert,
+					    algo);
     }
 
     while (rpmfiNext(hfi) >= 0) {
 	idx = rpmfiFX(hfi);
 	if (signatures[idx])
 	    continue;
-	signatures[idx] = rpmVeritySignFile(hfi, &sig_size, key, keypass, cert);
+	signatures[idx] = rpmVeritySignFile(hfi, &sig_size, key, keypass, cert,
+					    algo);
     }
 
     rpmtdReset(&td);
@@ -187,6 +194,23 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
 	signatures[idx] = NULL;
     }
 
+    if (sig_size == 0) {
+	rpmlog(RPMLOG_ERR, _("Zero length fsverity signature\n"));
+	rc = RPMRC_FAIL;
+	goto out;
+    }
+
+    rpmtdReset(&td);
+
+    /* RPM doesn't like new 16 bit types, so use a 32 bit tag */
+    algo32 = algo;
+    rpmtdReset(&td);
+    td.tag = RPMSIGTAG_VERITYSIGNATUREALGO;
+    td.type = RPM_INT32_TYPE;
+    td.data = &algo32;
+    td.count = 1;
+    headerPut(sigh, &td, HEADERPUT_DEFAULT);
+
     rpmlog(RPMLOG_DEBUG, _("sigh size: %i\n"), headerSizeof(sigh, 0));
 
     rc = RPMRC_OK;
-- 
2.27.0