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