From e339fdbbd0b81dc1fcdc2032e861b8a5fa6e062d Mon Sep 17 00:00:00 2001 From: Jes Sorensen 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 --- 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