dcavalca / rpms / rpm

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