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>
This commit is contained in:
Bill Richardson
2015-10-15 00:23:18 -07:00
committed by chrome-bot
parent df0e1a391f
commit 02ac2885fd
6 changed files with 218 additions and 174 deletions

View File

@@ -29,6 +29,8 @@
#include "util_misc.h" #include "util_misc.h"
#include "vb1_helper.h" #include "vb1_helper.h"
#include "vboot_common.h" #include "vboot_common.h"
#include "2api.h"
#include "host_key2.h"
/* Options */ /* Options */
struct show_option_s show_option = { 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 { enum no_short_opts {
OPT_PADDING = 1000, OPT_PADDING = 1000,
OPT_TYPE, OPT_TYPE,
OPT_PUBKEY,
OPT_HELP, OPT_HELP,
}; };
@@ -415,8 +418,8 @@ static const char usage[] = "\n"
" --type TYPE Override the detected file type\n" " --type TYPE Override the detected file type\n"
" Use \"--type help\" for a list\n" " Use \"--type help\" for a list\n"
"Type-specific options:\n" "Type-specific options:\n"
" -k|--publickey FILE" " -k|--publickey FILE.vbpubk Public key in vb1 format\n"
" Use this public key for validation\n" " --pubkey FILE.vpubk2 Public key in vb2 format\n"
" -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n" " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n"
" --pad NUM Kernel vblock padding size\n" " --pad NUM Kernel vblock padding size\n"
" --strict " " --strict "
@@ -441,6 +444,7 @@ static const struct option long_opts[] = {
{"pad", 1, NULL, OPT_PADDING}, {"pad", 1, NULL, OPT_PADDING},
{"type", 1, NULL, OPT_TYPE}, {"type", 1, NULL, OPT_TYPE},
{"strict", 0, &show_option.strict, 1}, {"strict", 0, &show_option.strict, 1},
{"pubkey", 1, NULL, OPT_PUBKEY},
{"help", 0, NULL, OPT_HELP}, {"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0}, {NULL, 0, NULL, 0},
}; };
@@ -528,6 +532,12 @@ static int do_show(int argc, char *argv[])
} }
type_override = 1; type_override = 1;
break; 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: case OPT_HELP:
print_help(argc, argv); print_help(argc, argv);
return !!errorcnt; return !!errorcnt;

View File

@@ -43,8 +43,7 @@ struct sign_option_s sign_option = {
.rw_size = 0xffffffff, .rw_size = 0xffffffff,
.ro_offset = 0xffffffff, .ro_offset = 0xffffffff,
.rw_offset = 0xffffffff, .rw_offset = 0xffffffff,
.pkey_offset = 0xffffffff, .sig_size = 1024,
.sig_offset = 0xffffffff,
}; };
/* Helper to complain about invalid args. Returns num errors discovered */ /* Helper to complain about invalid args. Returns num errors discovered */
@@ -424,7 +423,7 @@ static void print_help_usbpd1(int argc, char *argv[])
"\n" "\n"
"This signs a %s.\n" "This signs a %s.\n"
"\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" " sections,\n"
"with the public key at the end of of the RO section and the" "with the public key at the end of of the RO section and the"
" signature\n" " signature\n"
@@ -464,7 +463,6 @@ static void print_help_usbpd1(int argc, char *argv[])
"\n"); "\n");
} }
/* The rwsig help is the same as the usbpd1 help, for now anyway. */
static void print_help_rwsig(int argc, char *argv[]) static void print_help_rwsig(int argc, char *argv[])
{ {
printf("\n" printf("\n"
@@ -472,35 +470,30 @@ static void print_help_rwsig(int argc, char *argv[])
"\n" "\n"
"This signs a %s.\n" "This signs a %s.\n"
"\n" "\n"
"The INPUT is assumed to consist of equal-sized RO and RW" "The INFILE is a binary blob of arbitrary size."
" sections.\n" " It is signed using the\n"
"Signing the RW image will put the signature in the RW half." "private key and the vb2_signature blob emitted.\n"
" If the public\n" "\n"
"key is provided, it will be copied to the RO half.\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" "\n"
"Options:\n" "Options:\n"
"\n" "\n"
" --prikey FILE.vbprik2 " " --prikey FILE.vbprik2 "
" Private key in vb2 format\n" "Private key in vb2 format (required)\n"
" --pubkey FILE.vbpubk2" " --sig_size NUM "
" Public key in vb2 format\n" "Offset from the end of INFILE where the\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"
"\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" "signature blob should be located\n"
" --pkey_offset NUM"
" Where to place the public key (default is\n"
" " " "
" near the end of the RO image)\n" "(default 1024 bytes)\n"
" --data_size NUM "
"Number of bytes of INFILE to sign\n"
"\n", "\n",
argv[0], argv[0],
futil_file_type_name(FILE_TYPE_RWSIG), 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" " raw linux kernel (vmlinuz) kernel partition image\n"
" kernel partition (/dev/sda2) same, or signed in-place\n" " kernel partition (/dev/sda2) same, or signed in-place\n"
" usbpd1 firmware image 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" "\n"
"For more information, use \"" MYNAME " help %s TYPE\", where\n" "For more information, use \"" MYNAME " help %s TYPE\", where\n"
"TYPE is one of:\n\n"; "TYPE is one of:\n\n";
@@ -575,10 +568,9 @@ enum no_short_opts {
OPT_RW_SIZE, OPT_RW_SIZE,
OPT_RO_OFFSET, OPT_RO_OFFSET,
OPT_RW_OFFSET, OPT_RW_OFFSET,
OPT_PKEY_OFFSET, OPT_DATA_SIZE,
OPT_SIG_OFFSET, OPT_SIG_SIZE,
OPT_PRIKEY, OPT_PRIKEY,
OPT_PUBKEY,
OPT_HELP, OPT_HELP,
}; };
@@ -614,11 +606,10 @@ static const struct option long_opts[] = {
{"rw_size", 1, NULL, OPT_RW_SIZE}, {"rw_size", 1, NULL, OPT_RW_SIZE},
{"ro_offset", 1, NULL, OPT_RO_OFFSET}, {"ro_offset", 1, NULL, OPT_RO_OFFSET},
{"rw_offset", 1, NULL, OPT_RW_OFFSET}, {"rw_offset", 1, NULL, OPT_RW_OFFSET},
{"pkey_offset", 1, NULL, OPT_PKEY_OFFSET}, {"data_size", 1, NULL, OPT_DATA_SIZE},
{"sig_offset", 1, NULL, OPT_SIG_OFFSET}, {"sig_size", 1, NULL, OPT_SIG_SIZE},
{"prikey", 1, NULL, OPT_PRIKEY}, {"prikey", 1, NULL, OPT_PRIKEY},
{"privkey", 1, NULL, OPT_PRIKEY}, /* alias */ {"privkey", 1, NULL, OPT_PRIKEY}, /* alias */
{"pubkey", 1, NULL, OPT_PUBKEY},
{"help", 0, NULL, OPT_HELP}, {"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0}, {NULL, 0, NULL, 0},
}; };
@@ -646,7 +637,6 @@ static int do_sign(int argc, char *argv[])
uint8_t *buf; uint8_t *buf;
uint32_t buf_len; uint32_t buf_len;
char *e = 0; char *e = 0;
int inout_file_count = 0;
int mapping; int mapping;
int helpind = 0; int helpind = 0;
int longindex; int longindex;
@@ -715,11 +705,11 @@ static int do_sign(int argc, char *argv[])
sign_option.fv_specified = 1; sign_option.fv_specified = 1;
/* fallthrough */ /* fallthrough */
case OPT_INFILE: case OPT_INFILE:
inout_file_count++; sign_option.inout_file_count++;
infile = optarg; infile = optarg;
break; break;
case OPT_OUTFILE: case OPT_OUTFILE:
inout_file_count++; sign_option.inout_file_count++;
sign_option.outfile = optarg; sign_option.outfile = optarg;
break; break;
case OPT_BOOTLOADER: case OPT_BOOTLOADER:
@@ -785,13 +775,13 @@ static int do_sign(int argc, char *argv[])
errorcnt += parse_number_opt(optarg, "rw_offset", errorcnt += parse_number_opt(optarg, "rw_offset",
&sign_option.rw_offset); &sign_option.rw_offset);
break; break;
case OPT_PKEY_OFFSET: case OPT_DATA_SIZE:
errorcnt += parse_number_opt(optarg, "pkey_offset", errorcnt += parse_number_opt(optarg, "data_size",
&sign_option.pkey_offset); &sign_option.data_size);
break; break;
case OPT_SIG_OFFSET: case OPT_SIG_SIZE:
errorcnt += parse_number_opt(optarg, "sig_offset", errorcnt += parse_number_opt(optarg, "sig_size",
&sign_option.sig_offset); &sign_option.sig_size);
break; break;
case OPT_PEM_SIGNPRIV: case OPT_PEM_SIGNPRIV:
sign_option.pem_signpriv = optarg; sign_option.pem_signpriv = optarg;
@@ -834,12 +824,6 @@ static int do_sign(int argc, char *argv[])
errorcnt++; errorcnt++;
} }
break; 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: case OPT_HELP:
helpind = optind - 1; helpind = optind - 1;
break; break;
@@ -882,14 +866,14 @@ static int do_sign(int argc, char *argv[])
fprintf(stderr, "ERROR: missing input filename\n"); fprintf(stderr, "ERROR: missing input filename\n");
goto done; goto done;
} else { } else {
inout_file_count++; sign_option.inout_file_count++;
infile = argv[optind++]; infile = argv[optind++];
} }
} }
/* Look for an output file if we don't have one, just in case. */ /* Look for an output file if we don't have one, just in case. */
if (!sign_option.outfile && argc - optind > 0) { if (!sign_option.outfile && argc - optind > 0) {
inout_file_count++; sign_option.inout_file_count++;
sign_option.outfile = argv[optind++]; sign_option.outfile = argv[optind++];
} }
@@ -945,7 +929,7 @@ static int do_sign(int argc, char *argv[])
break; break;
case FILE_TYPE_KERN_PREAMBLE: case FILE_TYPE_KERN_PREAMBLE:
errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); 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; sign_option.create_new_outfile = 1;
break; break;
case FILE_TYPE_RAW_FIRMWARE: case FILE_TYPE_RAW_FIRMWARE:
@@ -982,7 +966,7 @@ static int do_sign(int argc, char *argv[])
} }
Debug("infile=%s\n", infile); 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", Debug("sign_option.create_new_outfile=%d\n",
sign_option.create_new_outfile); sign_option.create_new_outfile);
@@ -1021,7 +1005,7 @@ static int do_sign(int argc, char *argv[])
} else { } else {
/* We'll read-modify-write the output file */ /* We'll read-modify-write the output file */
mapping = MAP_RW; mapping = MAP_RW;
if (inout_file_count > 1) if (sign_option.inout_file_count > 1)
futil_copy_file_or_die(infile, sign_option.outfile); futil_copy_file_or_die(infile, sign_option.outfile);
Debug("open RW %s\n", sign_option.outfile); Debug("open RW %s\n", sign_option.outfile);
infile = 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, errorcnt += futil_file_type_sign(sign_option.type, infile,
buf, buf_len); buf, buf_len);
errorcnt += futil_unmap_file(ifd, MAP_RW, buf, buf_len); errorcnt += futil_unmap_file(ifd, mapping, buf, buf_len);
done: done:
if (ifd >= 0 && close(ifd)) { if (ifd >= 0 && close(ifd)) {

View File

@@ -71,9 +71,9 @@ FILE_TYPE(CHROMIUMOS_DISK, "disk_img", "chromiumos disk image",
NONE, NONE,
NONE, NONE,
NONE) NONE)
FILE_TYPE(RWSIG, "rwsig", "RO+RW firmware image", FILE_TYPE(RWSIG, "rwsig", "RW device image",
NONE, R_(ft_recognize_rwsig),
NONE, S_(ft_show_rwsig),
S_(ft_sign_rwsig)) S_(ft_sign_rwsig))
/* Firmware for USB Type-C power adapters */ /* Firmware for USB Type-C power adapters */
FILE_TYPE(USBPD1, "usbpd1", "USB-PD charger image (v1.0)", FILE_TYPE(USBPD1, "usbpd1", "USB-PD charger image (v1.0)",

View File

@@ -30,112 +30,160 @@
#include "host_signature2.h" #include "host_signature2.h"
#include "util_misc.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 #define SIGNATURE_RSVD_SIZE 1024
/* True if start + size > max */ static inline void vb2_print_bytes(const void *ptr, uint32_t len)
static int bigger_than(uint32_t start, uint32_t size, uint32_t max)
{ {
int r = start > max || size > max || start > max - size; const uint8_t *buf = (const uint8_t *)ptr;
if (r) int i;
Debug("%s: 0x%x + 0x%x > 0x%x\n", __func__, start, size, max); for (i = 0; i < len; i++)
return r; printf("%02x", *buf++);
} }
/* True if one region overlaps the other */ static void show_sig(const char *name, const struct vb2_signature *sig)
static int overlaps(uint32_t start_a, uint32_t size_a,
uint32_t start_b, uint32_t size_b)
{ {
if (start_a < start_b && start_a <= start_b - size_a) const struct vb2_text_vs_enum *entry;
return 0; printf("Signature: %s\n", name);
if (start_b < start_a && start_b <= start_a - size_b) printf(" Vboot API: 2.1\n");
return 0; printf(" Desc: \"%s\"\n", vb2_common_desc(sig));
Debug("%s: 0x%x + 0x%x overlaps 0x%x + 0x%x\n", entry = vb2_lookup_by_num(vb2_text_vs_sig, sig->sig_alg);
__func__, start_a, size_a, start_b, size_b); 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);
}
int ft_show_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin)
{
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; return 1;
} }
/* Return 1 if okay, 0 if not */ sig = (const struct vb2_signature *)(buf + len - sig_size);
static int parse_size_opts(const uint8_t *buf, uint32_t len, if (VB2_SUCCESS == vb2_verify_signature(sig, sig_size)) {
uint32_t *rw_offset_ptr, uint32_t *rw_size_ptr, show_sig(name, sig);
uint32_t *pkey_offset_ptr, uint32_t *sig_offset_ptr) data = buf;
{ data_size = sig->data_size;
uint32_t rw_offset, rw_size, pkey_offset, sig_offset; } else {
return 1;
/* 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;
} }
*rw_offset_ptr = rw_offset; if (!show_option.pkey) {
*rw_size_ptr = rw_size; printf("No public key available to verify with\n");
*pkey_offset_ptr = pkey_offset; return show_option.strict;
*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) int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *data)
{ {
struct vb2_signature *sig = 0; struct vb2_signature *sig = 0;
uint32_t r, data_size = len, sig_size = SIGNATURE_RSVD_SIZE;
int retval = 1; 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(): name %s\n", __func__, name);
Debug("%s(): len 0x%08x (%d)\n", __func__, len, len); Debug("%s(): len 0x%08x (%d)\n", __func__, len, len);
/* Figure out what to sign and where to put the blobs */ /* If we don't have a distinct OUTFILE, look for an existing sig */
if (!parse_size_opts(buf, len, if (sign_option.inout_file_count < 2) {
&rw_offset, &rw_size, const struct vb2_signature *old_sig;
&pkey_offset, &sig_offset))
goto done; /* 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 */ /* Sign the blob */
r = vb2_sign_data(&sig, buf + rw_offset, rw_size, r = vb2_sign_data(&sig, buf, data_size, sign_option.prikey, 0);
sign_option.prikey, 0);
if (r) { if (r) {
fprintf(stderr, fprintf(stderr,
"Unable to sign data (error 0x%08x, if that helps)\n", "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; goto done;
} }
Debug("sig_offset 0x%08x\n", sig_offset); if (sign_option.inout_file_count < 2) {
Debug("sig_size 0x%08x\n", sig->c.total_size); /* Overwrite the old signature */
if (sig->c.total_size > sig_size) {
if (sig->c.total_size > SIGNATURE_RSVD_SIZE) fprintf(stderr, "New sig is too large (%d > %d)\n",
fprintf(stderr, "WARNING: The signature may be too large" sig->c.total_size, sig_size);
" (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; goto done;
} }
memset(buf + len - sig_size, 0xff, sig_size);
Debug("pkey_offset 0x%08x\n", pkey_offset); memcpy(buf + len - sig_size, sig, sig->c.total_size);
Debug("pkey_size 0x%08x\n", sign_option.pkey->c.total_size); } else {
/* Write the signature to a new file */
if (sign_option.pkey->c.total_size > PUBKEY_RSVD_SIZE) r = vb2_write_object(sign_option.outfile, sig);
fprintf(stderr, "WARNING: The public key may be too large" if (r) {
" (0x%08x > %08x)\n", fprintf(stderr, "Unable to write sig"
sign_option.pkey->c.total_size, PUBKEY_RSVD_SIZE); " (error 0x%08x, if that helps)\n", r);
goto done;
/* Update the public key */ }
memcpy(buf + pkey_offset, sign_option.pkey, }
sign_option.pkey->c.total_size);
/* Finally */ /* Finally */
retval = 0; retval = 0;
done: done:
if (sig)
free(sig);
if (sign_option.prikey) if (sign_option.prikey)
vb2_private_key_free(sign_option.prikey); vb2_private_key_free(sign_option.prikey);
if (sign_option.pkey)
free(sign_option.pkey);
return retval; 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;
}

View File

@@ -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; uint32_t ro_size, rw_size, ro_offset, rw_offset;
int s, h; 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 * 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 * signature, in order to identify blob as the right type we have to

View File

@@ -27,6 +27,8 @@ struct show_option_s {
int strict; int strict;
int t_flag; int t_flag;
enum futil_file_type type; enum futil_file_type type;
struct vb2_packed_key *pkey;
uint32_t sig_size;
}; };
extern struct show_option_s show_option; extern struct show_option_s show_option;
@@ -53,6 +55,7 @@ struct sign_option_s {
int vblockonly; int vblockonly;
char *outfile; char *outfile;
int create_new_outfile; int create_new_outfile;
int inout_file_count;
char *pem_signpriv; char *pem_signpriv;
int pem_algo_specified; int pem_algo_specified;
uint32_t pem_algo; uint32_t pem_algo;
@@ -61,9 +64,8 @@ struct sign_option_s {
enum vb2_hash_algorithm hash_alg; enum vb2_hash_algorithm hash_alg;
uint32_t ro_size, rw_size; uint32_t ro_size, rw_size;
uint32_t ro_offset, rw_offset; 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_private_key *prikey;
struct vb2_packed_key *pkey;
}; };
extern struct sign_option_s sign_option; extern struct sign_option_s sign_option;