summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2015-10-15 00:23:18 -0700
committerchrome-bot <chrome-bot@chromium.org>2015-10-15 19:57:13 -0700
commit02ac2885fd797fba7f12ef040f0eb041dda7af20 (patch)
tree8c8386e3fc07bb5f7cc8c5c485cf10a58dec1340
parentdf0e1a391fa7b8d7bdb31f9623fbbcbb158cd2ad (diff)
downloadvboot-02ac2885fd797fba7f12ef040f0eb041dda7af20.tar.gz
futility: Revised support for RO+RW firmware
The "rwsig" type is used for independent device firmware (not Chromebook BIOS) that need to verify themselves instead of using software sync. The expected use case is that a RO firmware contains a vb2_public_key struct along with an FMAP or other pointers to a slot for RW firmware. The RW firmware slot reserves room for a vb2_signature struct. This CL changes the args and behavior of the rwsig type, so that the RW firmware can be [re]signed independently of the rest of the image. BUG=chrome-os-partner:46254 BRANCH=smaug,ToT TEST=make runtests, manual Create a keypair: futility create --desc "Key One" tests/testkeys/key_rsa2048.pem foo Sign a RW binary and build a complete image out of the parts: futility sign --type rwsig --prikey foo.vbprik2 rw.bin sig.bin dd if=/dev/zero bs=65536 count=1 of=image.bin dd if=rw.bin of=image.bin conv=notrunc dd if=sig.bin bs=$((65536 - 1024)) seek=1 of=image.bin conv=notrunc Verify both the separate parts and the combined image: futility show --type rwsig --pubkey foo.vbpubk2 rw.bin sig.bin futility show --type rwsig --pubkey foo.vbpubk2 image.bin Re-sign the combined image with a different keypair: futility create --desc "Key Two" tests/testkeys/key_rsa1024.pem bar futility sign --type rwsig --prikey bar.vbprik2 image.bin Now the first key no longer verifies: futility show --type rwsig --pubkey foo.vbpubk2 image.bin But the second key does: futility show --type rwsig --pubkey bar.vbpubk2 image.bin Change-Id: Ifdddab08f218f506eb1dce28851b153d70140a7b Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/305980 Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--futility/cmd_show.c14
-rw-r--r--futility/cmd_sign.c100
-rw-r--r--futility/file_type.inc6
-rw-r--r--futility/file_type_rwsig.c274
-rw-r--r--futility/file_type_usbpd1.c2
-rw-r--r--futility/futility_options.h6
6 files changed, 223 insertions, 179 deletions
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index 5d6c7c2b..8b33d1af 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -29,6 +29,8 @@
#include "util_misc.h"
#include "vb1_helper.h"
#include "vboot_common.h"
+#include "2api.h"
+#include "host_key2.h"
/* Options */
struct show_option_s show_option = {
@@ -395,6 +397,7 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
enum no_short_opts {
OPT_PADDING = 1000,
OPT_TYPE,
+ OPT_PUBKEY,
OPT_HELP,
};
@@ -415,8 +418,8 @@ static const char usage[] = "\n"
" --type TYPE Override the detected file type\n"
" Use \"--type help\" for a list\n"
"Type-specific options:\n"
- " -k|--publickey FILE"
- " Use this public key for validation\n"
+ " -k|--publickey FILE.vbpubk Public key in vb1 format\n"
+ " --pubkey FILE.vpubk2 Public key in vb2 format\n"
" -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n"
" --pad NUM Kernel vblock padding size\n"
" --strict "
@@ -441,6 +444,7 @@ static const struct option long_opts[] = {
{"pad", 1, NULL, OPT_PADDING},
{"type", 1, NULL, OPT_TYPE},
{"strict", 0, &show_option.strict, 1},
+ {"pubkey", 1, NULL, OPT_PUBKEY},
{"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
@@ -528,6 +532,12 @@ static int do_show(int argc, char *argv[])
}
type_override = 1;
break;
+ case OPT_PUBKEY:
+ if (vb2_packed_key_read(&show_option.pkey, optarg)) {
+ fprintf(stderr, "Error reading %s\n", optarg);
+ errorcnt++;
+ }
+ break;
case OPT_HELP:
print_help(argc, argv);
return !!errorcnt;
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index e6184f43..c27f71e8 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -43,8 +43,7 @@ struct sign_option_s sign_option = {
.rw_size = 0xffffffff,
.ro_offset = 0xffffffff,
.rw_offset = 0xffffffff,
- .pkey_offset = 0xffffffff,
- .sig_offset = 0xffffffff,
+ .sig_size = 1024,
};
/* Helper to complain about invalid args. Returns num errors discovered */
@@ -424,7 +423,7 @@ static void print_help_usbpd1(int argc, char *argv[])
"\n"
"This signs a %s.\n"
"\n"
- "The INPUT is assumed to consist of equal-sized RO and RW"
+ "The INFILE is assumed to consist of equal-sized RO and RW"
" sections,\n"
"with the public key at the end of of the RO section and the"
" signature\n"
@@ -464,7 +463,6 @@ static void print_help_usbpd1(int argc, char *argv[])
"\n");
}
-/* The rwsig help is the same as the usbpd1 help, for now anyway. */
static void print_help_rwsig(int argc, char *argv[])
{
printf("\n"
@@ -472,35 +470,30 @@ static void print_help_rwsig(int argc, char *argv[])
"\n"
"This signs a %s.\n"
"\n"
- "The INPUT is assumed to consist of equal-sized RO and RW"
- " sections.\n"
- "Signing the RW image will put the signature in the RW half."
- " If the public\n"
- "key is provided, it will be copied to the RO half.\n"
+ "The INFILE is a binary blob of arbitrary size."
+ " It is signed using the\n"
+ "private key and the vb2_signature blob emitted.\n"
"\n"
- "Options:\n"
- "\n"
- " --prikey FILE.vbprik2"
- " Private key in vb2 format\n"
- " --pubkey FILE.vbpubk2"
- " Public key in vb2 format\n"
+ "If no OUTFILE is specified, the INFILE should contain"
+ " an existing\n"
+ "vb2_signature blob near its end. The data_size from that"
+ " signature is\n"
+ "used to re-sign a portion of the INFILE, and the old"
+ " signature blob is\n"
+ "replaced.\n"
"\n"
- "The size and offset assumptions can be overridden. "
- "All numbers are in bytes.\n"
- "Specify a size of 0 to ignore that section.\n"
+ "Options:\n"
"\n"
- " --rw_size NUM"
- " Size of the RW section (default half)\n"
- " --rw_offset NUM"
- " Start of the RW section (default half)\n"
- " --sig_offset NUM"
- " Where to place the signature (default is\n"
- " "
- " near the end of the RW image)\n"
- " --pkey_offset NUM"
- " Where to place the public key (default is\n"
- " "
- " near the end of the RO image)\n"
+ " --prikey FILE.vbprik2 "
+ "Private key in vb2 format (required)\n"
+ " --sig_size NUM "
+ "Offset from the end of INFILE where the\n"
+ " "
+ "signature blob should be located\n"
+ " "
+ "(default 1024 bytes)\n"
+ " --data_size NUM "
+ "Number of bytes of INFILE to sign\n"
"\n",
argv[0],
futil_file_type_name(FILE_TYPE_RWSIG),
@@ -529,7 +522,7 @@ static const char usage_default[] = "\n"
" raw linux kernel (vmlinuz) kernel partition image\n"
" kernel partition (/dev/sda2) same, or signed in-place\n"
" usbpd1 firmware image same, or signed in-place\n"
- " RO+RW firmware image same, or signed in-place\n"
+ " RW device image same, or signed in-place\n"
"\n"
"For more information, use \"" MYNAME " help %s TYPE\", where\n"
"TYPE is one of:\n\n";
@@ -575,10 +568,9 @@ enum no_short_opts {
OPT_RW_SIZE,
OPT_RO_OFFSET,
OPT_RW_OFFSET,
- OPT_PKEY_OFFSET,
- OPT_SIG_OFFSET,
+ OPT_DATA_SIZE,
+ OPT_SIG_SIZE,
OPT_PRIKEY,
- OPT_PUBKEY,
OPT_HELP,
};
@@ -614,11 +606,10 @@ static const struct option long_opts[] = {
{"rw_size", 1, NULL, OPT_RW_SIZE},
{"ro_offset", 1, NULL, OPT_RO_OFFSET},
{"rw_offset", 1, NULL, OPT_RW_OFFSET},
- {"pkey_offset", 1, NULL, OPT_PKEY_OFFSET},
- {"sig_offset", 1, NULL, OPT_SIG_OFFSET},
+ {"data_size", 1, NULL, OPT_DATA_SIZE},
+ {"sig_size", 1, NULL, OPT_SIG_SIZE},
{"prikey", 1, NULL, OPT_PRIKEY},
{"privkey", 1, NULL, OPT_PRIKEY}, /* alias */
- {"pubkey", 1, NULL, OPT_PUBKEY},
{"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
@@ -646,7 +637,6 @@ static int do_sign(int argc, char *argv[])
uint8_t *buf;
uint32_t buf_len;
char *e = 0;
- int inout_file_count = 0;
int mapping;
int helpind = 0;
int longindex;
@@ -715,11 +705,11 @@ static int do_sign(int argc, char *argv[])
sign_option.fv_specified = 1;
/* fallthrough */
case OPT_INFILE:
- inout_file_count++;
+ sign_option.inout_file_count++;
infile = optarg;
break;
case OPT_OUTFILE:
- inout_file_count++;
+ sign_option.inout_file_count++;
sign_option.outfile = optarg;
break;
case OPT_BOOTLOADER:
@@ -785,13 +775,13 @@ static int do_sign(int argc, char *argv[])
errorcnt += parse_number_opt(optarg, "rw_offset",
&sign_option.rw_offset);
break;
- case OPT_PKEY_OFFSET:
- errorcnt += parse_number_opt(optarg, "pkey_offset",
- &sign_option.pkey_offset);
+ case OPT_DATA_SIZE:
+ errorcnt += parse_number_opt(optarg, "data_size",
+ &sign_option.data_size);
break;
- case OPT_SIG_OFFSET:
- errorcnt += parse_number_opt(optarg, "sig_offset",
- &sign_option.sig_offset);
+ case OPT_SIG_SIZE:
+ errorcnt += parse_number_opt(optarg, "sig_size",
+ &sign_option.sig_size);
break;
case OPT_PEM_SIGNPRIV:
sign_option.pem_signpriv = optarg;
@@ -834,12 +824,6 @@ static int do_sign(int argc, char *argv[])
errorcnt++;
}
break;
- case OPT_PUBKEY:
- if (vb2_packed_key_read(&sign_option.pkey, optarg)) {
- fprintf(stderr, "Error reading %s\n", optarg);
- errorcnt++;
- }
- break;
case OPT_HELP:
helpind = optind - 1;
break;
@@ -882,14 +866,14 @@ static int do_sign(int argc, char *argv[])
fprintf(stderr, "ERROR: missing input filename\n");
goto done;
} else {
- inout_file_count++;
+ sign_option.inout_file_count++;
infile = argv[optind++];
}
}
/* Look for an output file if we don't have one, just in case. */
if (!sign_option.outfile && argc - optind > 0) {
- inout_file_count++;
+ sign_option.inout_file_count++;
sign_option.outfile = argv[optind++];
}
@@ -945,7 +929,7 @@ static int do_sign(int argc, char *argv[])
break;
case FILE_TYPE_KERN_PREAMBLE:
errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
- if (sign_option.vblockonly || inout_file_count > 1)
+ if (sign_option.vblockonly || sign_option.inout_file_count > 1)
sign_option.create_new_outfile = 1;
break;
case FILE_TYPE_RAW_FIRMWARE:
@@ -982,7 +966,7 @@ static int do_sign(int argc, char *argv[])
}
Debug("infile=%s\n", infile);
- Debug("inout_file_count=%d\n", inout_file_count);
+ Debug("sign_option.inout_file_count=%d\n", sign_option.inout_file_count);
Debug("sign_option.create_new_outfile=%d\n",
sign_option.create_new_outfile);
@@ -1021,7 +1005,7 @@ static int do_sign(int argc, char *argv[])
} else {
/* We'll read-modify-write the output file */
mapping = MAP_RW;
- if (inout_file_count > 1)
+ if (sign_option.inout_file_count > 1)
futil_copy_file_or_die(infile, sign_option.outfile);
Debug("open RW %s\n", sign_option.outfile);
infile = sign_option.outfile;
@@ -1042,7 +1026,7 @@ static int do_sign(int argc, char *argv[])
errorcnt += futil_file_type_sign(sign_option.type, infile,
buf, buf_len);
- errorcnt += futil_unmap_file(ifd, MAP_RW, buf, buf_len);
+ errorcnt += futil_unmap_file(ifd, mapping, buf, buf_len);
done:
if (ifd >= 0 && close(ifd)) {
diff --git a/futility/file_type.inc b/futility/file_type.inc
index fd12286f..07db5011 100644
--- a/futility/file_type.inc
+++ b/futility/file_type.inc
@@ -71,9 +71,9 @@ FILE_TYPE(CHROMIUMOS_DISK, "disk_img", "chromiumos disk image",
NONE,
NONE,
NONE)
-FILE_TYPE(RWSIG, "rwsig", "RO+RW firmware image",
- NONE,
- NONE,
+FILE_TYPE(RWSIG, "rwsig", "RW device image",
+ R_(ft_recognize_rwsig),
+ S_(ft_show_rwsig),
S_(ft_sign_rwsig))
/* Firmware for USB Type-C power adapters */
FILE_TYPE(USBPD1, "usbpd1", "USB-PD charger image (v1.0)",
diff --git a/futility/file_type_rwsig.c b/futility/file_type_rwsig.c
index 6b757fff..e50ff32f 100644
--- a/futility/file_type_rwsig.c
+++ b/futility/file_type_rwsig.c
@@ -30,112 +30,160 @@
#include "host_signature2.h"
#include "util_misc.h"
-/*
- * Reserved space for the public key and signature. This may not be enough for
- * larger key sizes since the vb2 structs are more than just the raw bits.
- */
-#define PUBKEY_RSVD_SIZE 2048
#define SIGNATURE_RSVD_SIZE 1024
-/* True if start + size > max */
-static int bigger_than(uint32_t start, uint32_t size, uint32_t max)
+static inline void vb2_print_bytes(const void *ptr, uint32_t len)
{
- int r = start > max || size > max || start > max - size;
- if (r)
- Debug("%s: 0x%x + 0x%x > 0x%x\n", __func__, start, size, max);
- return r;
+ const uint8_t *buf = (const uint8_t *)ptr;
+ int i;
+ for (i = 0; i < len; i++)
+ printf("%02x", *buf++);
}
-/* True if one region overlaps the other */
-static int overlaps(uint32_t start_a, uint32_t size_a,
- uint32_t start_b, uint32_t size_b)
+static void show_sig(const char *name, const struct vb2_signature *sig)
{
- if (start_a < start_b && start_a <= start_b - size_a)
- return 0;
- if (start_b < start_a && start_b <= start_a - size_b)
- return 0;
- Debug("%s: 0x%x + 0x%x overlaps 0x%x + 0x%x\n",
- __func__, start_a, size_a, start_b, size_b);
- return 1;
+ const struct vb2_text_vs_enum *entry;
+ printf("Signature: %s\n", name);
+ printf(" Vboot API: 2.1\n");
+ printf(" Desc: \"%s\"\n", vb2_common_desc(sig));
+ entry = vb2_lookup_by_num(vb2_text_vs_sig, sig->sig_alg);
+ printf(" Signature Algorithm: %d %s\n", sig->sig_alg,
+ entry ? entry->name : "(invalid)");
+ entry = vb2_lookup_by_num(vb2_text_vs_hash, sig->hash_alg);
+ printf(" Hash Algorithm: %d %s\n", sig->hash_alg,
+ entry ? entry->name : "(invalid)");
+ printf(" Total size: 0x%x (%d)\n", sig->c.total_size,
+ sig->c.total_size);
+ printf(" ID: ");
+ vb2_print_bytes(&sig->id, sizeof(sig->id));
+ printf("\n");
+ printf(" Data size: 0x%x (%d)\n", sig->data_size,
+ sig->data_size);
}
-/* Return 1 if okay, 0 if not */
-static int parse_size_opts(const uint8_t *buf, uint32_t len,
- uint32_t *rw_offset_ptr, uint32_t *rw_size_ptr,
- uint32_t *pkey_offset_ptr, uint32_t *sig_offset_ptr)
+int ft_show_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin)
{
- uint32_t rw_offset, rw_size, pkey_offset, sig_offset;
-
- /* Start with defaults */
-
- /* The image has both RO and RW, evenly split, RO first. */
- rw_size = rw_offset = len / 2;
-
- /* The public key is up against the end of the RO half */
- pkey_offset = rw_offset - PUBKEY_RSVD_SIZE;
-
- /* The signature key is up against the end of the whole image */
- sig_offset = len - SIGNATURE_RSVD_SIZE;
-
- /* The RW image to be signed doesn't include the signature */
- rw_size -= SIGNATURE_RSVD_SIZE;
-
- /* FIXME: Override the defaults here by looking for an FMAP or similar
- * structure telling us where the parts are. */
-
- /* We can override any of that with explicit args */
- if (sign_option.rw_offset != 0xffffffff)
- rw_offset = sign_option.rw_offset;
- if (sign_option.rw_size != 0xffffffff)
- rw_size = sign_option.rw_size;
- if (sign_option.pkey_offset != 0xffffffff)
- pkey_offset = sign_option.pkey_offset;
- if (sign_option.sig_offset != 0xffffffff)
- sig_offset = sign_option.sig_offset;
-
- Debug("pkey_offset 0x%08x\n", pkey_offset);
- Debug("rw_offset 0x%08x\n", rw_offset);
- Debug("rw_size 0x%08x\n", rw_size);
- Debug("sig_offset 0x%08x\n", sig_offset);
-
- /* Now let's do some sanity checks. */
- if (bigger_than(rw_offset, rw_size, len) ||
- overlaps(rw_offset, rw_size, pkey_offset, PUBKEY_RSVD_SIZE) ||
- overlaps(rw_offset, rw_size, sig_offset, SIGNATURE_RSVD_SIZE) ||
- overlaps(pkey_offset, PUBKEY_RSVD_SIZE,
- sig_offset, SIGNATURE_RSVD_SIZE)) {
- printf("size/offset values are bogus\n");
- return 0;
+ const struct vb2_signature *sig = 0;
+ struct vb2_public_key key;
+ uint8_t workbuf[VB2_VERIFY_DATA_WORKBUF_BYTES]
+ __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
+ struct vb2_workbuf wb;
+ uint32_t data_size, sig_size = SIGNATURE_RSVD_SIZE;
+ uint8_t *data;
+
+ Debug("%s(): name %s\n", __func__, name);
+ Debug("%s(): len 0x%08x (%d)\n", __func__, len, len);
+
+ /* Am I just looking at a signature file? */
+ Debug("Looking for signature at 0x0\n");
+ sig = (const struct vb2_signature *)buf;
+ if (VB2_SUCCESS == vb2_verify_signature(sig, len)) {
+ show_sig(name, sig);
+ if (!show_option.fv) {
+ printf("No data available to verify\n");
+ return show_option.strict;
+ }
+ data = show_option.fv;
+ data_size = show_option.fv_size;
+ } else {
+ /* Where would it be? */
+ if (show_option.sig_size)
+ sig_size = show_option.sig_size;
+
+ Debug("Looking for signature at 0x%x\n", len - sig_size);
+
+ if (len < sig_size) {
+ Debug("File is too small\n");
+ return 1;
+ }
+
+ sig = (const struct vb2_signature *)(buf + len - sig_size);
+ if (VB2_SUCCESS == vb2_verify_signature(sig, sig_size)) {
+ show_sig(name, sig);
+ data = buf;
+ data_size = sig->data_size;
+ } else {
+ return 1;
+ }
+ }
+
+ if (!show_option.pkey) {
+ printf("No public key available to verify with\n");
+ return show_option.strict;
}
- *rw_offset_ptr = rw_offset;
- *rw_size_ptr = rw_size;
- *pkey_offset_ptr = pkey_offset;
- *sig_offset_ptr = sig_offset;
+ /* We already did this once, so it should work again */
+ if (vb2_unpack_key(&key,
+ (const uint8_t *)show_option.pkey,
+ show_option.pkey->c.total_size)) {
+ Debug("Can't unpack pubkey\n");
+ return 1;
+ }
- return 1;
+ /* The sig is destroyed by the verify operation, so make a copy */
+ {
+ uint8_t sigbuf[sig->c.total_size];
+ memcpy(sigbuf, sig, sizeof(sigbuf));
+
+ vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
+
+ if (vb2_verify_data(data, data_size,
+ (struct vb2_signature *)sigbuf,
+ (const struct vb2_public_key *)&key,
+ &wb)) {
+ printf("Signature verification failed\n");
+ return 1;
+ }
+ }
+
+ printf("Signature verification succeeded.\n");
+ return 0;
}
int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *data)
{
struct vb2_signature *sig = 0;
+ uint32_t r, data_size = len, sig_size = SIGNATURE_RSVD_SIZE;
int retval = 1;
- uint32_t rw_offset, rw_size; /* what to sign */
- uint32_t pkey_offset, sig_offset; /* where to put blobs */
- uint32_t r;
Debug("%s(): name %s\n", __func__, name);
Debug("%s(): len 0x%08x (%d)\n", __func__, len, len);
- /* Figure out what to sign and where to put the blobs */
- if (!parse_size_opts(buf, len,
- &rw_offset, &rw_size,
- &pkey_offset, &sig_offset))
- goto done;
+ /* If we don't have a distinct OUTFILE, look for an existing sig */
+ if (sign_option.inout_file_count < 2) {
+ const struct vb2_signature *old_sig;
+
+ /* Where would it be? */
+ if (sign_option.sig_size)
+ sig_size = sign_option.sig_size;
+
+ Debug("Looking for old signature at 0x%x\n", len - sig_size);
+
+ if (len < sig_size) {
+ fprintf(stderr, "File is too small\n");
+ return 1;
+ }
+
+ /* Take a look */
+ old_sig = (const struct vb2_signature *)(buf + len - sig_size);
+ if (vb2_verify_signature(old_sig, sig_size)) {
+ fprintf(stderr, "Can't find a valid signature\n");
+ return 1;
+ }
+
+ /* Use the same exent again */
+ data_size = old_sig->data_size;
+
+ Debug("Found sig: data_size is 0x%x (%d)\n", data_size,
+ data_size);
+ }
+
+ /* Unless overridden */
+ if (sign_option.data_size)
+ data_size = sign_option.data_size;
/* Sign the blob */
- r = vb2_sign_data(&sig, buf + rw_offset, rw_size,
- sign_option.prikey, 0);
+ r = vb2_sign_data(&sig, buf, data_size, sign_option.prikey, 0);
if (r) {
fprintf(stderr,
"Unable to sign data (error 0x%08x, if that helps)\n",
@@ -143,43 +191,45 @@ int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *data)
goto done;
}
- Debug("sig_offset 0x%08x\n", sig_offset);
- Debug("sig_size 0x%08x\n", sig->c.total_size);
-
- if (sig->c.total_size > SIGNATURE_RSVD_SIZE)
- fprintf(stderr, "WARNING: The signature may be too large"
- " (0x%08x > %08x)\n",
- sig->c.total_size, SIGNATURE_RSVD_SIZE);
-
- /* Update the signature */
- memcpy(buf + sig_offset, sig, sig->c.total_size);
-
- /* If weren't given a public key, we're done */
- if (!sign_option.pkey) {
- fprintf(stderr, "No public key given; not updating RO\n");
- retval = 0;
- goto done;
+ if (sign_option.inout_file_count < 2) {
+ /* Overwrite the old signature */
+ if (sig->c.total_size > sig_size) {
+ fprintf(stderr, "New sig is too large (%d > %d)\n",
+ sig->c.total_size, sig_size);
+ goto done;
+ }
+ memset(buf + len - sig_size, 0xff, sig_size);
+ memcpy(buf + len - sig_size, sig, sig->c.total_size);
+ } else {
+ /* Write the signature to a new file */
+ r = vb2_write_object(sign_option.outfile, sig);
+ if (r) {
+ fprintf(stderr, "Unable to write sig"
+ " (error 0x%08x, if that helps)\n", r);
+ goto done;
+ }
}
- Debug("pkey_offset 0x%08x\n", pkey_offset);
- Debug("pkey_size 0x%08x\n", sign_option.pkey->c.total_size);
-
- if (sign_option.pkey->c.total_size > PUBKEY_RSVD_SIZE)
- fprintf(stderr, "WARNING: The public key may be too large"
- " (0x%08x > %08x)\n",
- sign_option.pkey->c.total_size, PUBKEY_RSVD_SIZE);
-
- /* Update the public key */
- memcpy(buf + pkey_offset, sign_option.pkey,
- sign_option.pkey->c.total_size);
-
/* Finally */
retval = 0;
done:
+ if (sig)
+ free(sig);
if (sign_option.prikey)
vb2_private_key_free(sign_option.prikey);
- if (sign_option.pkey)
- free(sign_option.pkey);
return retval;
}
+
+enum futil_file_type ft_recognize_rwsig(uint8_t *buf, uint32_t len)
+{
+ if (!vb2_verify_signature((const struct vb2_signature *)buf, len))
+ return FILE_TYPE_RWSIG;
+
+ if (!vb2_verify_signature((const struct vb2_signature *)
+ (buf + len - SIGNATURE_RSVD_SIZE),
+ SIGNATURE_RSVD_SIZE))
+ return FILE_TYPE_RWSIG;
+
+ return FILE_TYPE_UNKNOWN;
+}
diff --git a/futility/file_type_usbpd1.c b/futility/file_type_usbpd1.c
index 36cb5cf2..c0f5397e 100644
--- a/futility/file_type_usbpd1.c
+++ b/futility/file_type_usbpd1.c
@@ -465,8 +465,6 @@ enum futil_file_type ft_recognize_usbpd1(uint8_t *buf, uint32_t len)
uint32_t ro_size, rw_size, ro_offset, rw_offset;
int s, h;
- Debug("%s(): len 0x%08x (%d)\n", __func__, len, len);
-
/*
* Since we don't use any headers to identify or locate the pubkey and
* signature, in order to identify blob as the right type we have to
diff --git a/futility/futility_options.h b/futility/futility_options.h
index e02ef2f6..3a6aecb6 100644
--- a/futility/futility_options.h
+++ b/futility/futility_options.h
@@ -27,6 +27,8 @@ struct show_option_s {
int strict;
int t_flag;
enum futil_file_type type;
+ struct vb2_packed_key *pkey;
+ uint32_t sig_size;
};
extern struct show_option_s show_option;
@@ -53,6 +55,7 @@ struct sign_option_s {
int vblockonly;
char *outfile;
int create_new_outfile;
+ int inout_file_count;
char *pem_signpriv;
int pem_algo_specified;
uint32_t pem_algo;
@@ -61,9 +64,8 @@ struct sign_option_s {
enum vb2_hash_algorithm hash_alg;
uint32_t ro_size, rw_size;
uint32_t ro_offset, rw_offset;
- uint32_t pkey_offset, sig_offset;
+ uint32_t data_size, sig_size;
struct vb2_private_key *prikey;
- struct vb2_packed_key *pkey;
};
extern struct sign_option_s sign_option;