malmond / rpms / rpm

Forked from rpms/rpm 4 years ago
Clone

Blame SOURCES/0022-rpmsignverity-Add-verity-signature-headers-to-the-pa.patch

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