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(¶ms, 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