aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kerr <jeremy.kerr@canonical.com>2012-06-12 16:56:15 +0800
committerJeremy Kerr <jeremy.kerr@canonical.com>2012-06-12 17:47:38 +0800
commitedf1d26d49c08580d8b9022be6429ccbab825533 (patch)
tree4c79e3a8a8cf9bb6bb0eb401ec71a77fee645310
parentbe7559abfe05a6456fca5e5b1ab7d84c6aff1a5b (diff)
downloadsbsigntools-edf1d26d49c08580d8b9022be6429ccbab825533.tar.gz
sbattach: Add too to manage detached signatures
Add a third tool (`sbattach`) to attach and detach signatures from PE/COFF files. Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-rw-r--r--Makefile.am6
-rw-r--r--sbattach.c236
2 files changed, 241 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 8b5c431..a87cb5a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
AM_CFLAGS = -Wall -Wextra
-bin_PROGRAMS = sbsign sbverify
+bin_PROGRAMS = sbsign sbverify sbattach
coff_headers = coff/external.h coff/pe.h coff/i386.h coff/x86_64.h
@@ -17,6 +17,10 @@ sbverify_SOURCES = sbverify.c $(common_SOURCES)
sbverify_LDADD = $(common_LDADD)
sbverify_CFLAGS = $(AM_CFLAGS) $(common_CFLAGS)
+sbattach_SOURCES = sbattach.c $(common_SOURCES)
+sbattach_LDADD = $(common_LDADD)
+sbattach_CFLAGS = $(AM_CFLAGS) $(common_CFLAGS)
+
man1_MANS = docs/sbsign.1 docs/sbverify.1
EXTRA_DIST = docs/sbsign.1.in docs/sbverify.1.in
diff --git a/sbattach.c b/sbattach.c
new file mode 100644
index 0000000..7cce654
--- /dev/null
+++ b/sbattach.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include <ccan/talloc/talloc.h>
+#include <ccan/read_write_all/read_write_all.h>
+
+#include "config.h"
+
+#include "image.h"
+
+static const char *toolname = "sbattach";
+
+static struct option options[] = {
+ { "attach", required_argument, NULL, 'a' },
+ { "detach", required_argument, NULL, 'd' },
+ { "remove", no_argument, NULL, 'r' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 },
+};
+
+static void usage(void)
+{
+ printf("Usage: %s --attach <sigfile> <efi-boot-image>\n"
+ " or: %s --detach <sigfile> [--remove] <efi-boot-image>\n"
+ " or: %s --remove <efi-boot-image>\n"
+ "Attach or detach a signature file to/from a boot image\n"
+ "\n"
+ "Options:\n"
+ "\t--attach <sigfile> set <sigfile> as the boot image's\n"
+ "\t signature table\n"
+ "\t--detach <sigfile> copy the boot image's signature table\n"
+ "\t to <sigfile>\n"
+ "\t--remove remove the boot image's signature\n"
+ "\t table from the original file\n",
+ toolname, toolname, toolname);
+}
+
+static void version(void)
+{
+ printf("%s %s\n", toolname, VERSION);
+}
+
+static int detach_sig(struct image *image, const char *sig_filename)
+{
+ return image_write_detached(image, sig_filename);
+}
+
+static int attach_sig(struct image *image, const char *image_filename,
+ const char *sig_filename)
+{
+ struct stat statbuf;
+ uint8_t *sigbuf;
+ size_t size;
+ int fd, rc;
+
+ sigbuf = NULL;
+
+ fd = open(sig_filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Can't open file %s: %s\n", sig_filename,
+ strerror(errno));
+ return -1;
+ }
+
+ rc = fstat(fd, &statbuf);
+ if (rc) {
+ perror("fstat");
+ goto out;
+ }
+
+ size = statbuf.st_size;
+
+ sigbuf = talloc_array(image, uint8_t, size);
+ if (!sigbuf) {
+ perror("talloc");
+ goto out;
+ }
+
+ rc = read_all(fd, sigbuf, size);
+ if (!rc) {
+ fprintf(stderr, "Error reading %s: %s\n", sig_filename,
+ strerror(errno));
+ goto out;
+ }
+
+ image->sigbuf = sigbuf;
+ image->sigsize = size;
+
+ rc = image_write(image, image_filename);
+ if (rc)
+ fprintf(stderr, "Error writing %s: %s\n", image_filename,
+ strerror(errno));
+
+out:
+ close(fd);
+ talloc_free(sigbuf);
+ return rc;
+}
+
+static int remove_sig(struct image *image, const char *image_filename)
+{
+ int rc;
+
+ image->sigbuf = NULL;
+ image->sigsize = 0;
+
+ rc = image_write(image, image_filename);
+ if (rc)
+ fprintf(stderr, "Error writing %s: %s\n", image_filename,
+ strerror(errno));
+
+ return rc;
+}
+
+enum action {
+ ACTION_NONE,
+ ACTION_ATTACH,
+ ACTION_DETACH,
+};
+
+int main(int argc, char **argv)
+{
+ const char *image_filename, *sig_filename;
+ struct image *image;
+ enum action action;
+ bool remove;
+ int c, rc;
+
+ action = ACTION_NONE;
+ sig_filename = NULL;
+ remove = false;
+
+ for (;;) {
+ int idx;
+ c = getopt_long(argc, argv, "a:d:rhV", options, &idx);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'a':
+ case 'd':
+ if (action != ACTION_NONE) {
+ fprintf(stderr, "Multiple actions specified\n");
+ usage();
+ return EXIT_FAILURE;
+ }
+ action = (c == 'a') ? ACTION_ATTACH : ACTION_DETACH;
+ sig_filename = optarg;
+ break;
+ case 'r':
+ remove = true;
+ break;
+ case 'V':
+ version();
+ return EXIT_SUCCESS;
+ case 'h':
+ usage();
+ return EXIT_SUCCESS;
+ }
+ }
+
+ if (argc != optind + 1) {
+ usage();
+ return EXIT_FAILURE;
+ }
+ image_filename = argv[optind];
+
+ /* sanity check action combinations */
+ if (action == ACTION_ATTACH && remove) {
+ fprintf(stderr, "Can't use --remove with --attach\n");
+ return EXIT_FAILURE;
+ }
+
+ if (action == ACTION_NONE && !remove) {
+ fprintf(stderr, "No action (attach/detach/remove) specified\n");
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ image = image_load(image_filename);
+ if (!image) {
+ fprintf(stderr, "Can't load image file %s\n", image_filename);
+ return EXIT_FAILURE;
+ }
+
+ image_pecoff_parse(image);
+
+ rc = 0;
+
+ if (action == ACTION_ATTACH)
+ rc = attach_sig(image, image_filename, sig_filename);
+
+ else if (action == ACTION_DETACH)
+ rc = detach_sig(image, sig_filename);
+
+ if (rc)
+ goto out;
+
+ if (remove)
+ rc = remove_sig(image, image_filename);
+
+out:
+ talloc_free(image);
+ return (rc == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}