|
|
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(¶ms, 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, ¶ms, &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(¶ms, 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 |
- ¶ms, &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 |
|