319 lines
8.5 KiB
Diff
319 lines
8.5 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Peter Jones <pjones@redhat.com>
|
||
|
Date: Fri, 11 Mar 2022 12:54:39 -0500
|
||
|
Subject: [PATCH] Add 'pesum', an authenticode digest generator.
|
||
|
|
||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||
|
---
|
||
|
src/pesum.c | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
src/.gitignore | 1 +
|
||
|
src/Makefile | 12 +++-
|
||
|
src/pesum.1.mdoc | 38 +++++++++++
|
||
|
4 files changed, 244 insertions(+), 2 deletions(-)
|
||
|
create mode 100644 src/pesum.c
|
||
|
create mode 100644 src/pesum.1.mdoc
|
||
|
|
||
|
diff --git a/src/pesum.c b/src/pesum.c
|
||
|
new file mode 100644
|
||
|
index 0000000..e4ddaf8
|
||
|
--- /dev/null
|
||
|
+++ b/src/pesum.c
|
||
|
@@ -0,0 +1,195 @@
|
||
|
+// SPDX-License-Identifier: GPLv2
|
||
|
+/*
|
||
|
+ * pesum.c - pesum command line tool
|
||
|
+ * Copyright Peter Jones <pjones@redhat.com>
|
||
|
+ */
|
||
|
+
|
||
|
+#include "fix_coverity.h"
|
||
|
+
|
||
|
+#include <err.h>
|
||
|
+#include <popt.h>
|
||
|
+
|
||
|
+#include <nss.h>
|
||
|
+#include <prerror.h>
|
||
|
+
|
||
|
+#include "pesign.h"
|
||
|
+#include "pesign_standalone.h"
|
||
|
+
|
||
|
+static struct {
|
||
|
+ int flag;
|
||
|
+ const char *name;
|
||
|
+} flag_names[] = {
|
||
|
+ {DAEMONIZE, "daemonize"},
|
||
|
+ {GENERATE_DIGEST, "hash"},
|
||
|
+ {GENERATE_SIGNATURE, "sign"},
|
||
|
+ {IMPORT_RAW_SIGNATURE, "import-raw-sig"},
|
||
|
+ {IMPORT_SIGNATURE, "import-sig"},
|
||
|
+ {IMPORT_SATTRS, "import-sattrs" },
|
||
|
+ {EXPORT_SATTRS, "export-sattrs" },
|
||
|
+ {EXPORT_SIGNATURE, "export-sig"},
|
||
|
+ {EXPORT_PUBKEY, "export-pubkey"},
|
||
|
+ {EXPORT_CERT, "export-cert"},
|
||
|
+ {REMOVE_SIGNATURE, "remove"},
|
||
|
+ {LIST_SIGNATURES, "list"},
|
||
|
+ {FLAG_LIST_END, NULL},
|
||
|
+};
|
||
|
+
|
||
|
+void
|
||
|
+print_flag_name(FILE *f, int flag)
|
||
|
+{
|
||
|
+ for (int i = 0; flag_names[i].flag != FLAG_LIST_END; i++) {
|
||
|
+ if (flag_names[i].flag == flag)
|
||
|
+ fprintf(f, "%s ", flag_names[i].name);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static long *verbose;
|
||
|
+
|
||
|
+long
|
||
|
+verbosity(void)
|
||
|
+{
|
||
|
+ if (!verbose)
|
||
|
+ return 0;
|
||
|
+ return *verbose;
|
||
|
+}
|
||
|
+
|
||
|
+int
|
||
|
+main(int argc, char *argv[])
|
||
|
+{
|
||
|
+ int rc;
|
||
|
+ SECStatus status;
|
||
|
+
|
||
|
+ char *digest_name = "sha256";
|
||
|
+ char *orig_digest_name = digest_name;
|
||
|
+ int padding = 1;
|
||
|
+ long verbose_cmd_line = 0;
|
||
|
+ const char *infile;
|
||
|
+
|
||
|
+ int action = GENERATE_DIGEST|PRINT_DIGEST;
|
||
|
+ file_format fmt = FORMAT_PE_BINARY;
|
||
|
+
|
||
|
+ setenv("NSS_DEFAULT_DB_TYPE", "sql", 0);
|
||
|
+
|
||
|
+ verbose = &verbose_cmd_line;
|
||
|
+
|
||
|
+ poptContext optCon;
|
||
|
+ struct poptOption options[] = {
|
||
|
+ {.argInfo = POPT_ARG_INTL_DOMAIN,
|
||
|
+ .arg = "pesum" },
|
||
|
+ {.longName = "verbose",
|
||
|
+ .shortName = 'v',
|
||
|
+ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL,
|
||
|
+ .arg = &verbose_cmd_line,
|
||
|
+ .val = 1,
|
||
|
+ .descrip = "be more verbose" },
|
||
|
+ {.longName = "debug",
|
||
|
+ .shortName = '\0',
|
||
|
+ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL,
|
||
|
+ .arg = &verbose_cmd_line,
|
||
|
+ .val = 2,
|
||
|
+ .descrip = "be very verbose" },
|
||
|
+ {.longName = "digest-type",
|
||
|
+ .shortName = 'd',
|
||
|
+ .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT,
|
||
|
+ .arg = &digest_name,
|
||
|
+ .descrip = "digest type to use for pe hash" },
|
||
|
+ {.longName = "digest_type",
|
||
|
+ .shortName = '\0',
|
||
|
+ .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN,
|
||
|
+ .arg = &digest_name,
|
||
|
+ .descrip = "digest type to use for pe hash" },
|
||
|
+ {.longName = "padding",
|
||
|
+ .shortName = 'P',
|
||
|
+ .argInfo = POPT_ARG_VAL,
|
||
|
+ .arg = &padding,
|
||
|
+ .val = 1,
|
||
|
+ .descrip = "pad data section (default)" },
|
||
|
+ {.longName = "nopadding",
|
||
|
+ .shortName = 'p',
|
||
|
+ .argInfo = POPT_ARG_VAL,
|
||
|
+ .arg = &padding,
|
||
|
+ .val = 0,
|
||
|
+ .descrip = "do not pad the data section" },
|
||
|
+ POPT_AUTOALIAS
|
||
|
+ POPT_AUTOHELP
|
||
|
+ POPT_TABLEEND
|
||
|
+ };
|
||
|
+
|
||
|
+ optCon = poptGetContext("pesum", argc, (const char **)argv, options,0);
|
||
|
+
|
||
|
+ rc = poptReadDefaultConfig(optCon, 0);
|
||
|
+ if (rc < 0 && !(rc == POPT_ERROR_ERRNO && errno == ENOENT))
|
||
|
+ errx(1, "poptReadDefaultConfig failed: %s", poptStrerror(rc));
|
||
|
+
|
||
|
+ while ((rc = poptGetNextOpt(optCon)) > 0) {
|
||
|
+ ;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (rc < -1)
|
||
|
+ errx(1, "Invalid argument: %s: %s",
|
||
|
+ poptBadOption(optCon, 0), poptStrerror(rc));
|
||
|
+
|
||
|
+ if (!poptPeekArg(optCon))
|
||
|
+ errx(1, "nothing to do");
|
||
|
+
|
||
|
+ status = NSS_NoDB_Init(NULL);
|
||
|
+ if (status != SECSuccess)
|
||
|
+ errx(1, "Could not initialize nss.\n"
|
||
|
+ "NSS says \"%s\" errno says \"%m\"\n",
|
||
|
+ PORT_ErrorToString(PORT_GetError()));
|
||
|
+
|
||
|
+ while ((infile = poptGetArg(optCon)) != NULL) {
|
||
|
+ pesign_context *ctxp = NULL;
|
||
|
+
|
||
|
+ char *ext = strrchr(infile, '.');
|
||
|
+ if (ext && strcmp(ext, ".ko") == 0)
|
||
|
+ fmt = FORMAT_KERNEL_MODULE;
|
||
|
+
|
||
|
+ rc = pesign_context_new(&ctxp);
|
||
|
+ if (rc < 0)
|
||
|
+ err(1, "Could not initialize context");
|
||
|
+
|
||
|
+ ctxp->verbose = verbose_cmd_line;
|
||
|
+
|
||
|
+ ctxp->hash = 1;
|
||
|
+ ctxp->infile = strdup(infile);
|
||
|
+ if (!ctxp->infile)
|
||
|
+ err(1, "Could not allocate memory");
|
||
|
+
|
||
|
+ rc = set_digest_parameters(ctxp->cms_ctx, digest_name);
|
||
|
+ int is_help = strcmp(digest_name, "help") ? 0 : 1;
|
||
|
+ if (rc < 0) {
|
||
|
+ if (!is_help) {
|
||
|
+ fprintf(stderr, "Digest \"%s\" not found.\n",
|
||
|
+ digest_name);
|
||
|
+ }
|
||
|
+ exit(!is_help);
|
||
|
+ }
|
||
|
+
|
||
|
+ errno = 0;
|
||
|
+ switch (fmt) {
|
||
|
+ case FORMAT_PE_BINARY:
|
||
|
+ pe_handle_action(ctxp, action, padding);
|
||
|
+ break;
|
||
|
+ case FORMAT_KERNEL_MODULE:
|
||
|
+ kmod_handle_action(ctxp, action);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ pesign_context_free(ctxp);
|
||
|
+ }
|
||
|
+
|
||
|
+ poptFreeContext(optCon);
|
||
|
+
|
||
|
+ if (digest_name && digest_name != orig_digest_name)
|
||
|
+ free(digest_name);
|
||
|
+
|
||
|
+ status = NSS_Shutdown();
|
||
|
+ if (status != SECSuccess)
|
||
|
+ errx(1, "could not shut down NSS: %s",
|
||
|
+ PORT_ErrorToString(PORT_GetError()));
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+// vim:fenc=utf-8:tw=75:noet
|
||
|
diff --git a/src/.gitignore b/src/.gitignore
|
||
|
index 64ce217..f8f6d66 100644
|
||
|
--- a/src/.gitignore
|
||
|
+++ b/src/.gitignore
|
||
|
@@ -5,6 +5,7 @@ client
|
||
|
efikeygen
|
||
|
efidbtool
|
||
|
pesigcheck
|
||
|
+pesum
|
||
|
peverify
|
||
|
pesign.service
|
||
|
pesign.sysvinit
|
||
|
diff --git a/src/Makefile b/src/Makefile
|
||
|
index 7010514..79cf09e 100644
|
||
|
--- a/src/Makefile
|
||
|
+++ b/src/Makefile
|
||
|
@@ -6,7 +6,7 @@ include $(TOPDIR)/Make.rules
|
||
|
include $(TOPDIR)/Make.defaults
|
||
|
|
||
|
BINTARGETS=authvar client efikeygen pesigcheck pesign \
|
||
|
- pesign-rpmbuild-helper pesign-authorize
|
||
|
+ pesign-rpmbuild-helper pesign-authorize pesum
|
||
|
CFGTARGETS=tmpfiles.conf
|
||
|
SVCTARGETS=pesign.sysvinit pesign.service
|
||
|
MAN1TARGETS=authvar.1 efikeygen.1 pesigcheck.1 pesign-client.1 pesign.1
|
||
|
@@ -29,9 +29,12 @@ EFIKEYGEN_SOURCES = efikeygen.c
|
||
|
PESIGCHECK_SOURCES = pesigcheck.c pesigcheck_context.c certdb.c
|
||
|
PESIGN_SOURCES = pesign.c pesign_context.c actions.c daemon.c \
|
||
|
file_pe.c file_kmod.c pesign_kmod.c
|
||
|
+PESUM_SOURCES = pesum.c pesign_context.c actions.c \
|
||
|
+ file_pe.c file_kmod.c pesign_kmod.c
|
||
|
|
||
|
ALL_SOURCES=$(COMMON_SOURCES) $(AUTHVAR_SORUCES) $(CLIENT_SOURCES) \
|
||
|
- $(EFIKEYGEN_SOURCES) $(PESIGCHECK_SOURCES) $(PESIGN_SOURCES)
|
||
|
+ $(EFIKEYGEN_SOURCES) $(PESIGCHECK_SOURCES) $(PESIGN_SOURCES) \
|
||
|
+ $(PESUM_SOURCES)
|
||
|
-include $(call deps-of,$(ALL_SOURCES))
|
||
|
|
||
|
authvar : $(call objects-of,$(AUTHVAR_SOURCES) $(COMMON_SOURCES))
|
||
|
@@ -53,6 +56,10 @@ pesign : $(call objects-of,$(PESIGN_SOURCES) $(COMMON_SOURCES) $(COMMON_PE_SOURC
|
||
|
pesign : LDLIBS+=$(TOPDIR)/libdpe/libdpe.a
|
||
|
pesign : PKGS=efivar nss nspr popt
|
||
|
|
||
|
+pesum : $(call objects-of,$(PESUM_SOURCES) $(COMMON_SOURCES) $(COMMON_PE_SOURCES))
|
||
|
+pesum : LDLIBS+=$(TOPDIR)/libdpe/libdpe.a
|
||
|
+pesum : PKGS=efivar nss nspr popt
|
||
|
+
|
||
|
deps : PKGS=efivar nss nspr popt uuid
|
||
|
deps : $(ALL_SOURCES)
|
||
|
$(MAKE) -f $(TOPDIR)/Make.deps \
|
||
|
@@ -81,6 +88,7 @@ install :
|
||
|
$(INSTALL) -d -m 755 $(INSTALLROOT)$(bindir)
|
||
|
$(INSTALL) -m 755 authvar $(INSTALLROOT)$(bindir)
|
||
|
$(INSTALL) -m 755 pesign $(INSTALLROOT)$(bindir)
|
||
|
+ $(INSTALL) -m 755 pesum $(INSTALLROOT)$(bindir)
|
||
|
$(INSTALL) -m 755 client $(INSTALLROOT)$(bindir)pesign-client
|
||
|
$(INSTALL) -m 755 efikeygen $(INSTALLROOT)$(bindir)
|
||
|
$(INSTALL) -m 755 pesigcheck $(INSTALLROOT)$(bindir)
|
||
|
diff --git a/src/pesum.1.mdoc b/src/pesum.1.mdoc
|
||
|
new file mode 100644
|
||
|
index 0000000..edd08ce
|
||
|
--- /dev/null
|
||
|
+++ b/src/pesum.1.mdoc
|
||
|
@@ -0,0 +1,38 @@
|
||
|
+.Dd $Mdocdate: Mar 11 2022$
|
||
|
+.Dt PESUM 1
|
||
|
+.Os Linux
|
||
|
+.Sh NAME
|
||
|
+.Nm pesum
|
||
|
+.Nd tool for generating Authenticode digests
|
||
|
+.Sh SYNOPSIS
|
||
|
+.Nm
|
||
|
+.Bk -words
|
||
|
+.Ar file0.efi
|
||
|
+.Op Ar file1.efi ...
|
||
|
+.Sh DESCRIPTION
|
||
|
+.Nm
|
||
|
+is a command line tool to generate Authenticode digests of PE binaries.
|
||
|
+.Sh EXAMPLES
|
||
|
+.Ss Getting the Authenticode digest of some files
|
||
|
+host:$ \fBpesum shimx64.efi grubx64.efi\fR
|
||
|
+8c5806e66bb5b052ebf860e1722474269cff3dde588610df21dbe8cf12c08390\ shimx64.efi
|
||
|
+546a71319c22da1d81879383c4c74be06d1c374bdecfafc9fcc80bd541802bfc\ grubx64.efi
|
||
|
+.Sh STANDARDS
|
||
|
+.Rs
|
||
|
+.%B Portable Executable
|
||
|
+.%I Microsoft
|
||
|
+.%D August 26, 2019
|
||
|
+.%U https://docs.microsoft.com/en-us/windows/win32/debug/pe-format\ \&
|
||
|
+.Re
|
||
|
+
|
||
|
+.Rs
|
||
|
+.%B Windows Authenticode Portable Executable Signature Format
|
||
|
+.%I Microsoft
|
||
|
+.%D March 21, 2008
|
||
|
+.%U https://web.archive.org/web/20130518222430/http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/Authenticode_PE.docx\ \&
|
||
|
+.Re
|
||
|
+.Sh SEE ALSO
|
||
|
+.Xr pesign 1
|
||
|
+.LP
|
||
|
+.Sh AUTHORS
|
||
|
+.An Peter Jones
|