chantra / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone
45afda
From ef819fecfed22cab2ccbd128e5ede33db8f2d3e9 Mon Sep 17 00:00:00 2001
45afda
From: Jes Sorensen <jsorensen@fb.com>
45afda
Date: Thu, 9 Apr 2020 12:58:17 -0400
45afda
Subject: [PATCH 21/33] rpmsignverity: Add verity signature headers to the
45afda
 package
45afda
45afda
This adds the array of verity signatures, and a signature length
45afda
header. We use 4K block for the Merkle tree, and rely on the kernel
45afda
doing the right thing.
45afda
45afda
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
45afda
---
45afda
 lib/rpmtag.h         |   6 ++-
45afda
 sign/rpmsignverity.c | 112 +++++++++++++++++++++++++++++--------------
45afda
 sign/rpmsignverity.h |   7 +++
45afda
 3 files changed, 87 insertions(+), 38 deletions(-)
45afda
45afda
diff --git a/lib/rpmtag.h b/lib/rpmtag.h
45afda
index 40ff5fa5d..478457ecb 100644
45afda
--- a/lib/rpmtag.h
45afda
+++ b/lib/rpmtag.h
45afda
@@ -67,6 +67,7 @@ typedef enum rpmTag_e {
45afda
     RPMTAG_SHA256HEADER		= RPMTAG_SIG_BASE+17,	/* s */
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
 
45afda
     RPMTAG_NAME  		= 1000,	/* s */
45afda
 #define	RPMTAG_N	RPMTAG_NAME	/* s */
45afda
@@ -427,8 +428,9 @@ typedef enum rpmSigTag_e {
45afda
     RPMSIGTAG_LONGSIZE	= RPMTAG_LONGSIGSIZE,	/*!< internal Header+Payload size (64bit) in bytes. */
45afda
     RPMSIGTAG_LONGARCHIVESIZE = RPMTAG_LONGARCHIVESIZE, /*!< internal uncompressed payload size (64bit) in bytes. */
45afda
     RPMSIGTAG_SHA256	= RPMTAG_SHA256HEADER,
45afda
-    RPMSIGTAG_FILESIGNATURES           = RPMTAG_SIG_BASE + 18,
45afda
-    RPMSIGTAG_FILESIGNATURELENGTH      = RPMTAG_SIG_BASE + 19,
45afda
+    RPMSIGTAG_FILESIGNATURES		= RPMTAG_SIG_BASE + 18,
45afda
+    RPMSIGTAG_FILESIGNATURELENGTH	= RPMTAG_SIG_BASE + 19,
45afda
+    RPMSIGTAG_VERITYSIGNATURES		= RPMTAG_VERITYSIGNATURES,
45afda
 } rpmSigTag;
45afda
 
45afda
 
45afda
diff --git a/sign/rpmsignverity.c b/sign/rpmsignverity.c
45afda
index 5346c3bc8..a9818bd08 100644
45afda
--- a/sign/rpmsignverity.c
45afda
+++ b/sign/rpmsignverity.c
45afda
@@ -33,23 +33,66 @@ static int rpmVerityRead(void *opaque, void *buf, size_t size)
45afda
 	return retval;
45afda
 }
45afda
 
45afda
+static char *rpmVeritySignFile(rpmfi fi, size_t *sig_size, char *key,
45afda
+			       char *keypass, char *cert)
45afda
+{
45afda
+    struct libfsverity_merkle_tree_params params;
45afda
+    struct libfsverity_signature_params sig_params;
45afda
+    struct libfsverity_digest *digest = NULL;
45afda
+    rpm_loff_t file_size;
45afda
+    char *digest_hex, *sig_hex = NULL;
45afda
+    uint8_t *sig;
45afda
+    int status;
45afda
+
45afda
+    file_size = rpmfiFSize(fi);
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.block_size = RPM_FSVERITY_BLKSZ;
45afda
+    params.salt_size = 0 /* salt_size */;
45afda
+    params.salt = NULL /* salt */;
45afda
+    params.file_size = file_size;
45afda
+    status = libfsverity_compute_digest(fi, rpmVerityRead, &params, &digest);
45afda
+    if (status) {
45afda
+	rpmlog(RPMLOG_DEBUG, _("failed to compute digest\n"));
45afda
+	goto out;
45afda
+    }
45afda
+
45afda
+    digest_hex = pgpHexStr(digest->digest, digest->digest_size);
45afda
+    rpmlog(RPMLOG_DEBUG, _("digest(%i): %s\n"),
45afda
+	   digest->digest_size, digest_hex);
45afda
+    free(digest_hex);
45afda
+
45afda
+    memset(&sig_params, 0, sizeof(struct libfsverity_signature_params));
45afda
+    sig_params.keyfile = key;
45afda
+    sig_params.certfile = cert;
45afda
+    if (libfsverity_sign_digest(digest, &sig_params, &sig, sig_size)) {
45afda
+	rpmlog(RPMLOG_DEBUG, _("failed to sign digest\n"));
45afda
+	goto out;
45afda
+    }
45afda
+
45afda
+    sig_hex = pgpHexStr(sig, *sig_size + 1);
45afda
+ out:
45afda
+    free(digest);
45afda
+    free(sig);
45afda
+    return sig_hex;
45afda
+}
45afda
+
45afda
 rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
45afda
 		    char *keypass, char *cert)
45afda
 {
45afda
-    int rc, status;
45afda
+    int rc;
45afda
     FD_t gzdi;
45afda
     rpmfiles files = NULL;
45afda
     rpmfi fi = NULL;
45afda
     rpmts ts = rpmtsCreate();
45afda
-    struct libfsverity_digest *digest = NULL;
45afda
-    struct libfsverity_merkle_tree_params params;
45afda
-    struct libfsverity_signature_params sig_params;
45afda
+    struct rpmtd_s td;
45afda
     rpm_loff_t file_size;
45afda
     off_t offset = Ftell(fd);
45afda
     const char *compr;
45afda
     char *rpmio_flags = NULL;
45afda
-    char *digest_hex;
45afda
-    uint8_t *sig;
45afda
+    char *sig_hex;
45afda
     size_t sig_size;
45afda
 
45afda
     Fseek(fd, 0, SEEK_SET);
45afda
@@ -75,43 +118,40 @@ rpmRC rpmSignVerity(FD_t fd, Header sigh, Header h, char *key,
45afda
     fi = rpmfiNewArchiveReader(gzdi, files,
45afda
 			       RPMFI_ITER_READ_ARCHIVE_OMIT_HARDLINKS);
45afda
 
45afda
+    /*
45afda
+     * Should this be sigh from the cloned fd or the sigh we received?
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
     while (rpmfiNext(fi) >= 0) {
45afda
-	if (!S_ISREG(rpmfiFMode(fi)))
45afda
-	    continue;
45afda
 	file_size = rpmfiFSize(fi);
45afda
-	rpmlog(RPMLOG_DEBUG, _("file: %s, (size %li)\n"),
45afda
-	       rpmfiFN(fi), file_size);
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.block_size = sysconf(_SC_PAGESIZE);
45afda
-	params.salt_size = 0 /* salt_size */;
45afda
-	params.salt = NULL /* salt */;
45afda
-	params.file_size = file_size;
45afda
-	status = libfsverity_compute_digest(fi, rpmVerityRead,
45afda
-					    &params, &digest);
45afda
-	if (!status) {
45afda
-	    digest_hex = pgpHexStr(digest->digest, digest->digest_size);
45afda
-	    rpmlog(RPMLOG_DEBUG, _("digest(%i): %s\n"),
45afda
-		   digest->digest_size, digest_hex);
45afda
-	    free(digest_hex);
45afda
-	}
45afda
-	memset(&sig_params, 0, sizeof(struct libfsverity_signature_params));
45afda
-	sig_params.keyfile = key;
45afda
-	sig_params.certfile = cert;
45afda
-	if (libfsverity_sign_digest(digest, &sig_params, &sig, &sig_size)) {
45afda
-	    rpmlog(RPMLOG_DEBUG, _("failed to sign digest\n"));
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
+	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
-	rpmlog(RPMLOG_DEBUG, _("digest signing success\n"));
45afda
-
45afda
-	free(digest);
45afda
-	free(sig);
45afda
+	free(sig_hex);
45afda
     }
45afda
 
45afda
-out:
45afda
+    rpmlog(RPMLOG_DEBUG, _("sigh size: %i\n"), headerSizeof(sigh, 0));
45afda
+
45afda
+    rc = RPMRC_OK;
45afda
+ out:
45afda
     Fseek(fd, offset, SEEK_SET);
45afda
 
45afda
     rpmfilesFree(files);
45afda
diff --git a/sign/rpmsignverity.h b/sign/rpmsignverity.h
45afda
index f3ad3bb18..69bbaf7f7 100644
45afda
--- a/sign/rpmsignverity.h
45afda
+++ b/sign/rpmsignverity.h
45afda
@@ -8,6 +8,13 @@
45afda
 extern "C" {
45afda
 #endif
45afda
 
45afda
+/*
45afda
+ * Block size used to generate the Merkle tree for fsverity. For now
45afda
+ * we only support 4K blocks, if we ever decide to support different
45afda
+ * block sizes, we will need a tag to indicate this.
45afda
+ */
45afda
+#define RPM_FSVERITY_BLKSZ	4096
45afda
+
45afda
 /**
45afda
  * Sign file digests in header into signature header
45afda
  * @param fd		file descriptor of RPM
45afda
-- 
45afda
2.27.0
45afda