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