45e748
From 22420d9ee652a25357727b00585dc3cfe78b2a80 Mon Sep 17 00:00:00 2001
45e748
From: Jes Sorensen <jsorensen@fb.com>
45e748
Date: Mon, 13 Apr 2020 18:14:15 -0400
45e748
Subject: [PATCH 22/33] rpmSignVerity: Generate signatures for files not
45e748
 present in archive
45e748
45e748
This generates signatures for all files in the archive, then picks up
45e748
ghost files from the header metadata and generates signatures for them
45e748
as well. It finally submits them to RPMTAG_VERITYSIGNATURES in header
45e748
file order as we cannot rely on archive order and header order being
45e748
the same.
45e748
45e748
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
45e748
---
45e748
 lib/package.c        |  1 +
45e748
 sign/rpmsignverity.c | 55 ++++++++++++++++++++++++++++++++++----------
45e748
 2 files changed, 44 insertions(+), 12 deletions(-)
45e748
45e748
diff --git a/lib/package.c b/lib/package.c
45e748
index b7d996a12..c6108f686 100644
45e748
--- a/lib/package.c
45e748
+++ b/lib/package.c
45e748
@@ -45,6 +45,7 @@ struct taglate_s {
45e748
     { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1, 1 },
45e748
     { RPMSIGTAG_FILESIGNATURES, RPMTAG_FILESIGNATURES, 0, 1 },
45e748
     { RPMSIGTAG_FILESIGNATURELENGTH, RPMTAG_FILESIGNATURELENGTH, 1, 1 },
45e748
+    { RPMSIGTAG_VERITYSIGNATURES, RPMTAG_VERITYSIGNATURES, 0, 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/sign/rpmsignverity.c b/sign/rpmsignverity.c
45e748
index a9818bd08..3bb23a18d 100644
45e748
--- a/sign/rpmsignverity.c
45e748
+++ b/sign/rpmsignverity.c
45e748
@@ -41,7 +41,7 @@ static char *rpmVeritySignFile(rpmfi fi, size_t *sig_size, char *key,
45e748
     struct libfsverity_digest *digest = NULL;
45e748
     rpm_loff_t file_size;
45e748
     char *digest_hex, *sig_hex = NULL;
45e748
-    uint8_t *sig;
45e748
+    uint8_t *sig = NULL;
45e748
     int status;
45e748
 
45e748
     file_size = rpmfiFSize(fi);
45e748
@@ -72,7 +72,7 @@ static char *rpmVeritySignFile(rpmfi fi, size_t *sig_size, char *key,
45e748
 	goto out;
45e748
     }
45e748
 
45e748
-    sig_hex = pgpHexStr(sig, *sig_size + 1);
45e748
+    sig_hex = pgpHexStr(sig, *sig_size);
45e748
  out:
45e748
     free(digest);
45e748
     free(sig);
45e748
@@ -86,6 +86,7 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
45e748
     FD_t gzdi;
45e748
     rpmfiles files = NULL;
45e748
     rpmfi fi = NULL;
45e748
+    rpmfi hfi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_FLAGS_QUERY);
45e748
     rpmts ts = rpmtsCreate();
45e748
     struct rpmtd_s td;
45e748
     rpm_loff_t file_size;
45e748
@@ -93,11 +94,14 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
45e748
     const char *compr;
45e748
     char *rpmio_flags = NULL;
45e748
     char *sig_hex;
45e748
+    char **signatures = NULL;
45e748
     size_t sig_size;
45e748
+    int nr_files, idx;
45e748
 
45e748
     Fseek(fd, 0, SEEK_SET);
45e748
     rpmtsSetVSFlags(ts, RPMVSF_MASK_NODIGESTS | RPMVSF_MASK_NOSIGNATURES |
45e748
 		    RPMVSF_NOHDRCHK);
45e748
+
45e748
     rc = rpmReadPackageFile(ts, fd, "fsverity", &h);
45e748
     if (rc != RPMRC_OK) {
45e748
 	rpmlog(RPMLOG_DEBUG, _("%s: rpmReadPackageFile returned %i\n"),
45e748
@@ -113,6 +117,8 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
45e748
 
45e748
     gzdi = Fdopen(fdDup(Fileno(fd)), rpmio_flags);
45e748
     free(rpmio_flags);
45e748
+    if (!gzdi)
45e748
+	rpmlog(RPMLOG_DEBUG, _("Fdopen() failed\n"));
45e748
 
45e748
     files = rpmfilesNew(NULL, h, RPMTAG_BASENAMES, RPMFI_FLAGS_QUERY);
45e748
     fi = rpmfiNewArchiveReader(gzdi, files,
45e748
@@ -123,39 +129,64 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
45e748
      */
45e748
     headerDel(sigh, RPMSIGTAG_VERITYSIGNATURES);
45e748
 
45e748
-    rpmtdReset(&td);
45e748
-    td.tag = RPMSIGTAG_VERITYSIGNATURES;
45e748
-    td.type = RPM_STRING_ARRAY_TYPE;
45e748
-    td.count = 1;
45e748
+    /*
45e748
+     * The payload doesn't include special files, like ghost files, and
45e748
+     * we cannot rely on the file order in the payload to match that of
45e748
+     * the header. Instead we allocate an array of pointers and populate
45e748
+     * it as we go along. Then walk the header fi and account for the
45e748
+     * special files. Last we walk the array and populate the header.
45e748
+     */
45e748
+    nr_files = rpmfiFC(hfi);
45e748
+    signatures = xcalloc(nr_files, sizeof(char *));
45e748
+
45e748
+    rpmlog(RPMLOG_DEBUG, _("file count - header: %i, payload %i\n"),
45e748
+	   nr_files, rpmfiFC(fi));
45e748
 
45e748
     while (rpmfiNext(fi) >= 0) {
45e748
 	file_size = rpmfiFSize(fi);
45e748
+	idx = rpmfiFX(fi);
45e748
 
45e748
 	rpmlog(RPMLOG_DEBUG, _("file: %s, (size %li, link %s, idx %i)\n"),
45e748
 	       rpmfiFN(fi), file_size, rpmfiFLink(fi), rpmfiFX(fi));
45e748
 
45e748
-	sig_hex = rpmVeritySignFile(fi, &sig_size, key, keypass, cert);
45e748
+	signatures[idx] = rpmVeritySignFile(fi, &sig_size, key, keypass, cert);
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
+    }
45e748
+
45e748
+    rpmtdReset(&td);
45e748
+    td.tag = RPMSIGTAG_VERITYSIGNATURES;
45e748
+    td.type = RPM_STRING_ARRAY_TYPE;
45e748
+    td.count = 1;
45e748
+    for (idx = 0; idx < nr_files; idx++) {
45e748
+	sig_hex = signatures[idx];
45e748
 	td.data = &sig_hex;
45e748
-	rpmlog(RPMLOG_DEBUG, _("digest signed, len: %li\n"), sig_size);
45e748
-#if 0
45e748
-	rpmlog(RPMLOG_DEBUG, _("digest: %s\n"), (char *)sig_hex);
45e748
-#endif
45e748
 	if (!headerPut(sigh, &td, HEADERPUT_APPEND)) {
45e748
 	    rpmlog(RPMLOG_ERR, _("headerPutString failed\n"));
45e748
 	    rc = RPMRC_FAIL;
45e748
 	    goto out;
45e748
 	}
45e748
-	free(sig_hex);
45e748
+	rpmlog(RPMLOG_DEBUG, _("signature: %s\n"), signatures[idx]);
45e748
+	rpmlog(RPMLOG_DEBUG, _("digest signed, len: %li\n"), sig_size);
45e748
+	free(signatures[idx]);
45e748
+	signatures[idx] = NULL;
45e748
     }
45e748
 
45e748
     rpmlog(RPMLOG_DEBUG, _("sigh size: %i\n"), headerSizeof(sigh, 0));
45e748
 
45e748
     rc = RPMRC_OK;
45e748
  out:
45e748
+    signatures = _free(signatures);
45e748
     Fseek(fd, offset, SEEK_SET);
45e748
 
45e748
     rpmfilesFree(files);
45e748
     rpmfiFree(fi);
45e748
+    rpmfiFree(hfi);
45e748
     rpmtsFree(ts);
45e748
     return rc;
45e748
 }
45e748
-- 
45e748
2.27.0
45e748