futility: export options for the sign and show commands

This declares the options for the sign and show commands in a
header file.

We want to split the code for logically separate file types into
separate source files, but we don't want to have multiple
option-parsing routines, so that we can be sure we're using the
same option names consistently (for example, --hash_alg always
takes the same args and means the same thing).

BUG=chromium:231574
BRANCH=none
TEST=make runtests

Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Change-Id: I939bd19ba199b4c44eb41cff3571cff88df9a181
Reviewed-on: https://chromium-review.googlesource.com/262896
Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Bill Richardson
2015-03-26 16:34:28 -07:00
committed by ChromeOS Commit Bot
parent 453ecd1956
commit 1e35c3a511
3 changed files with 277 additions and 232 deletions

View File

@@ -24,6 +24,7 @@
#include "file_type.h" #include "file_type.h"
#include "fmap.h" #include "fmap.h"
#include "futility.h" #include "futility.h"
#include "futility_options.h"
#include "gbb_header.h" #include "gbb_header.h"
#include "host_common.h" #include "host_common.h"
#include "traversal.h" #include "traversal.h"
@@ -31,16 +32,8 @@
#include "vb1_helper.h" #include "vb1_helper.h"
#include "vboot_common.h" #include "vboot_common.h"
/* Local structure for args, etc. */ /* Options */
static struct local_data_s { struct show_option_s show_option = {
VbPublicKey *k;
uint8_t *fv;
uint64_t fv_size;
uint32_t padding;
int strict;
int t_flag;
enum futil_file_type type;
} option = {
.padding = 65536, .padding = 65536,
.type = FILE_TYPE_UNKNOWN, .type = FILE_TYPE_UNKNOWN,
}; };
@@ -278,7 +271,7 @@ int ft_show_gbb(const char *name, uint8_t *buf, uint32_t len, void *data)
int ft_show_keyblock(const char *name, uint8_t *buf, uint32_t len, void *data) int ft_show_keyblock(const char *name, uint8_t *buf, uint32_t len, void *data)
{ {
VbKeyBlockHeader *block = (VbKeyBlockHeader *)buf; VbKeyBlockHeader *block = (VbKeyBlockHeader *)buf;
VbPublicKey *sign_key = option.k; VbPublicKey *sign_key = show_option.k;
int good_sig = 0; int good_sig = 0;
int retval = 0; int retval = 0;
@@ -293,7 +286,7 @@ int ft_show_keyblock(const char *name, uint8_t *buf, uint32_t len, void *data)
KeyBlockVerify(block, len, sign_key, 0)) KeyBlockVerify(block, len, sign_key, 0))
good_sig = 1; good_sig = 1;
if (option.strict && (!sign_key || !good_sig)) if (show_option.strict && (!sign_key || !good_sig))
retval = 1; retval = 1;
show_keyblock(block, name, !!sign_key, good_sig); show_keyblock(block, name, !!sign_key, good_sig);
@@ -333,9 +326,9 @@ int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
{ {
VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf; VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf;
struct show_state_s *state = (struct show_state_s *)data; struct show_state_s *state = (struct show_state_s *)data;
VbPublicKey *sign_key = option.k; VbPublicKey *sign_key = show_option.k;
uint8_t *fv_data = option.fv; uint8_t *fv_data = show_option.fv;
uint64_t fv_size = option.fv_size; uint64_t fv_size = show_option.fv_size;
struct bios_area_s *fw_body_area = 0; struct bios_area_s *fw_body_area = 0;
int good_sig = 0; int good_sig = 0;
int retval = 0; int retval = 0;
@@ -371,7 +364,7 @@ int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
show_keyblock(key_block, name, !!sign_key, good_sig); show_keyblock(key_block, name, !!sign_key, good_sig);
if (option.strict && (!sign_key || !good_sig)) if (show_option.strict && (!sign_key || !good_sig))
retval = 1; retval = 1;
RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
@@ -428,7 +421,7 @@ int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
if (!fv_data) { if (!fv_data) {
printf("No firmware body available to verify.\n"); printf("No firmware body available to verify.\n");
if (option.strict) if (show_option.strict)
return 1; return 1;
return 0; return 0;
} }
@@ -449,7 +442,7 @@ done:
state->area[state->c].is_valid = 1; state->area[state->c].is_valid = 1;
} else { } else {
printf("Seems legit, but the signature is unverified.\n"); printf("Seems legit, but the signature is unverified.\n");
if (option.strict) if (show_option.strict)
retval = 1; retval = 1;
} }
@@ -509,7 +502,7 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
void *data) void *data)
{ {
VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf; VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf;
VbPublicKey *sign_key = option.k; VbPublicKey *sign_key = show_option.k;
uint8_t *kernel_blob = 0; uint8_t *kernel_blob = 0;
uint64_t kernel_size = 0; uint64_t kernel_size = 0;
int good_sig = 0; int good_sig = 0;
@@ -532,7 +525,7 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
printf("Kernel partition: %s\n", name); printf("Kernel partition: %s\n", name);
show_keyblock(key_block, NULL, !!sign_key, good_sig); show_keyblock(key_block, NULL, !!sign_key, good_sig);
if (option.strict && (!sign_key || !good_sig)) if (show_option.strict && (!sign_key || !good_sig))
retval = 1; retval = 1;
RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
@@ -586,14 +579,14 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
printf(" Flags: 0x%" PRIx32 "\n", flags); printf(" Flags: 0x%" PRIx32 "\n", flags);
/* Verify kernel body */ /* Verify kernel body */
if (option.fv) { if (show_option.fv) {
/* It's in a separate file, which we've already read in */ /* It's in a separate file, which we've already read in */
kernel_blob = option.fv; kernel_blob = show_option.fv;
kernel_size = option.fv_size; kernel_size = show_option.fv_size;
} else if (len > option.padding) { } else if (len > show_option.padding) {
/* It should be at an offset within the input file. */ /* It should be at an offset within the input file. */
kernel_blob = buf + option.padding; kernel_blob = buf + show_option.padding;
kernel_size = len - option.padding; kernel_size = len - show_option.padding;
} }
if (!kernel_blob) { if (!kernel_blob) {
@@ -661,7 +654,7 @@ static const struct option long_opts[] = {
{"fv", 1, 0, 'f'}, {"fv", 1, 0, 'f'},
{"pad", 1, NULL, OPT_PADDING}, {"pad", 1, NULL, OPT_PADDING},
{"type", 1, NULL, OPT_TYPE}, {"type", 1, NULL, OPT_TYPE},
{"strict", 0, &option.strict, 1}, {"strict", 0, &show_option.strict, 1},
{"help", 0, NULL, OPT_HELP}, {"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0}, {NULL, 0, NULL, 0},
}; };
@@ -712,25 +705,26 @@ static int do_show(int argc, char *argv[])
while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
switch (i) { switch (i) {
case 'f': case 'f':
option.fv = ReadFile(optarg, &option.fv_size); show_option.fv = ReadFile(optarg,
if (!option.fv) { &show_option.fv_size);
if (!show_option.fv) {
fprintf(stderr, "Error reading %s: %s\n", fprintf(stderr, "Error reading %s: %s\n",
optarg, strerror(errno)); optarg, strerror(errno));
errorcnt++; errorcnt++;
} }
break; break;
case 'k': case 'k':
option.k = PublicKeyRead(optarg); show_option.k = PublicKeyRead(optarg);
if (!option.k) { if (!show_option.k) {
fprintf(stderr, "Error reading %s\n", optarg); fprintf(stderr, "Error reading %s\n", optarg);
errorcnt++; errorcnt++;
} }
break; break;
case 't': case 't':
option.t_flag = 1; show_option.t_flag = 1;
break; break;
case OPT_PADDING: case OPT_PADDING:
option.padding = strtoul(optarg, &e, 0); show_option.padding = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e)) { if (!*optarg || (e && *e)) {
fprintf(stderr, fprintf(stderr,
"Invalid --padding \"%s\"\n", optarg); "Invalid --padding \"%s\"\n", optarg);
@@ -738,7 +732,8 @@ static int do_show(int argc, char *argv[])
} }
break; break;
case OPT_TYPE: case OPT_TYPE:
if (!futil_str_to_file_type(optarg, &option.type)) { if (!futil_str_to_file_type(optarg,
&show_option.type)) {
if (!strcasecmp("help", optarg)) if (!strcasecmp("help", optarg))
print_file_types_and_exit(errorcnt); print_file_types_and_exit(errorcnt);
fprintf(stderr, fprintf(stderr,
@@ -781,7 +776,7 @@ static int do_show(int argc, char *argv[])
return 1; return 1;
} }
if (option.t_flag) { if (show_option.t_flag) {
for (i = optind; i < argc; i++) for (i = optind; i < argc; i++)
errorcnt += show_type(argv[i]); errorcnt += show_type(argv[i]);
goto done; goto done;
@@ -804,7 +799,7 @@ static int do_show(int argc, char *argv[])
/* Allow the user to override the type */ /* Allow the user to override the type */
if (type_override) if (type_override)
type = option.type; type = show_option.type;
else else
type = futil_file_type_buf(buf, len); type = futil_file_type_buf(buf, len);
@@ -820,10 +815,10 @@ boo:
} }
done: done:
if (option.k) if (show_option.k)
free(option.k); free(show_option.k);
if (option.fv) if (show_option.fv)
free(option.fv); free(show_option.fv);
return !!errorcnt; return !!errorcnt;
} }
@@ -833,7 +828,7 @@ DECLARE_FUTIL_COMMAND(show, do_show, VBOOT_VERSION_ALL,
static int do_verify(int argc, char *argv[]) static int do_verify(int argc, char *argv[])
{ {
option.strict = 1; show_option.strict = 1;
return do_show(argc, argv); return do_show(argc, argv);
} }

View File

@@ -21,6 +21,7 @@
#include "file_type.h" #include "file_type.h"
#include "fmap.h" #include "fmap.h"
#include "futility.h" #include "futility.h"
#include "futility_options.h"
#include "gbb_header.h" #include "gbb_header.h"
#include "host_common.h" #include "host_common.h"
#include "kernel_blob.h" #include "kernel_blob.h"
@@ -29,36 +30,8 @@
#include "vb1_helper.h" #include "vb1_helper.h"
#include "vboot_common.h" #include "vboot_common.h"
/* Local structure for args, etc. */ /* Options */
static struct local_data_s { struct sign_option_s sign_option = {
VbPrivateKey *signprivate;
VbKeyBlockHeader *keyblock;
VbPublicKey *kernel_subkey;
VbPrivateKey *devsignprivate;
VbKeyBlockHeader *devkeyblock;
uint32_t version;
int version_specified;
uint32_t flags;
int flags_specified;
char *loemdir;
char *loemid;
uint8_t *bootloader_data;
uint64_t bootloader_size;
uint8_t *config_data;
uint64_t config_size;
enum arch_t arch;
int fv_specified;
uint32_t kloadaddr;
uint32_t padding;
int vblockonly;
char *outfile;
int create_new_outfile;
char *pem_signpriv;
int pem_algo_specified;
uint32_t pem_algo;
char *pem_external;
enum futil_file_type type;
} option = {
.version = 1, .version = 1,
.arch = ARCH_UNSPECIFIED, .arch = ARCH_UNSPECIFIED,
.kloadaddr = CROS_32BIT_ENTRY_ADDR, .kloadaddr = CROS_32BIT_ENTRY_ADDR,
@@ -66,7 +39,6 @@ static struct local_data_s {
.type = FILE_TYPE_UNKNOWN, .type = FILE_TYPE_UNKNOWN,
}; };
/* Helper to complain about invalid args. Returns num errors discovered */ /* Helper to complain about invalid args. Returns num errors discovered */
static int no_opt_if(int expr, const char *optname) static int no_opt_if(int expr, const char *optname)
{ {
@@ -118,34 +90,36 @@ int ft_sign_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data)
VbPublicKey *data_key = (VbPublicKey *)buf; VbPublicKey *data_key = (VbPublicKey *)buf;
VbKeyBlockHeader *vblock; VbKeyBlockHeader *vblock;
if (option.pem_signpriv) { if (sign_option.pem_signpriv) {
if (option.pem_external) { if (sign_option.pem_external) {
/* External signing uses the PEM file directly. */ /* External signing uses the PEM file directly. */
vblock = KeyBlockCreate_external( vblock = KeyBlockCreate_external(
data_key, data_key,
option.pem_signpriv, sign_option.pem_signpriv,
option.pem_algo, option.flags, sign_option.pem_algo, sign_option.flags,
option.pem_external); sign_option.pem_external);
} else { } else {
option.signprivate = PrivateKeyReadPem( sign_option.signprivate = PrivateKeyReadPem(
option.pem_signpriv, option.pem_algo); sign_option.pem_signpriv,
if (!option.signprivate) { sign_option.pem_algo);
if (!sign_option.signprivate) {
fprintf(stderr, fprintf(stderr,
"Unable to read PEM signing key: %s\n", "Unable to read PEM signing key: %s\n",
strerror(errno)); strerror(errno));
return 1; return 1;
} }
vblock = KeyBlockCreate(data_key, option.signprivate, vblock = KeyBlockCreate(data_key,
option.flags); sign_option.signprivate,
sign_option.flags);
} }
} else { } else {
/* Not PEM. Should already have a signing key. */ /* Not PEM. Should already have a signing key. */
vblock = KeyBlockCreate(data_key, option.signprivate, vblock = KeyBlockCreate(data_key, sign_option.signprivate,
option.flags); sign_option.flags);
} }
/* Write it out */ /* Write it out */
return WriteSomeParts(option.outfile, return WriteSomeParts(sign_option.outfile,
vblock, vblock->key_block_size, vblock, vblock->key_block_size,
NULL, 0); NULL, 0);
} }
@@ -203,8 +177,8 @@ static int fmap_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
case BIOS_FMAP_VBLOCK_A: case BIOS_FMAP_VBLOCK_A:
fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_A]; fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_A];
/* Preserve the flags if they're not specified */ /* Preserve the flags if they're not specified */
if (!option.flags_specified) if (!sign_option.flags_specified)
option.flags = preamble->flags; sign_option.flags = preamble->flags;
break; break;
case BIOS_FMAP_VBLOCK_B: case BIOS_FMAP_VBLOCK_B:
fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_B]; fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_B];
@@ -241,9 +215,9 @@ int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len,
kblob_data = CreateKernelBlob( kblob_data = CreateKernelBlob(
vmlinuz_data, vmlinuz_size, vmlinuz_data, vmlinuz_size,
option.arch, option.kloadaddr, sign_option.arch, sign_option.kloadaddr,
option.config_data, option.config_size, sign_option.config_data, sign_option.config_size,
option.bootloader_data, option.bootloader_size, sign_option.bootloader_data, sign_option.bootloader_size,
&kblob_size); &kblob_size);
if (!kblob_data) { if (!kblob_data) {
fprintf(stderr, "Unable to create kernel blob\n"); fprintf(stderr, "Unable to create kernel blob\n");
@@ -251,10 +225,13 @@ int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len,
} }
Debug("kblob_size = 0x%" PRIx64 "\n", kblob_size); Debug("kblob_size = 0x%" PRIx64 "\n", kblob_size);
vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, vblock_data = SignKernelBlob(kblob_data, kblob_size,
option.version, option.kloadaddr, sign_option.padding,
option.keyblock, option.signprivate, sign_option.version,
option.flags, &vblock_size); sign_option.kloadaddr,
sign_option.keyblock,
sign_option.signprivate,
sign_option.flags, &vblock_size);
if (!vblock_data) { if (!vblock_data) {
fprintf(stderr, "Unable to sign kernel blob\n"); fprintf(stderr, "Unable to sign kernel blob\n");
free(kblob_data); free(kblob_data);
@@ -264,15 +241,15 @@ int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len,
/* We should be creating a completely new output file. /* We should be creating a completely new output file.
* If not, something's wrong. */ * If not, something's wrong. */
if (!option.create_new_outfile) if (!sign_option.create_new_outfile)
DIE; DIE;
if (option.vblockonly) if (sign_option.vblockonly)
rv = WriteSomeParts(option.outfile, rv = WriteSomeParts(sign_option.outfile,
vblock_data, vblock_size, vblock_data, vblock_size,
NULL, 0); NULL, 0);
else else
rv = WriteSomeParts(option.outfile, rv = WriteSomeParts(sign_option.outfile,
vblock_data, vblock_size, vblock_data, vblock_size,
kblob_data, kblob_size); kblob_data, kblob_size);
@@ -294,7 +271,7 @@ int ft_sign_kern_preamble(const char *name, uint8_t *buf, uint32_t len,
kpart_size = len; kpart_size = len;
/* Note: This just sets some static pointers. It doesn't malloc. */ /* Note: This just sets some static pointers. It doesn't malloc. */
kblob_data = UnpackKPart(kpart_data, kpart_size, option.padding, kblob_data = UnpackKPart(kpart_data, kpart_size, sign_option.padding,
&keyblock, &preamble, &kblob_size); &keyblock, &preamble, &kblob_size);
if (!kblob_data) { if (!kblob_data) {
@@ -309,50 +286,54 @@ int ft_sign_kern_preamble(const char *name, uint8_t *buf, uint32_t len,
* it here either. To enable it, we'd need to update the zeropage * it here either. To enable it, we'd need to update the zeropage
* table's cmd_line_ptr as well as the preamble. * table's cmd_line_ptr as well as the preamble.
*/ */
option.kloadaddr = preamble->body_load_address; sign_option.kloadaddr = preamble->body_load_address;
/* Replace the config if asked */ /* Replace the config if asked */
if (option.config_data && if (sign_option.config_data &&
0 != UpdateKernelBlobConfig(kblob_data, kblob_size, 0 != UpdateKernelBlobConfig(kblob_data, kblob_size,
option.config_data, sign_option.config_data,
option.config_size)) { sign_option.config_size)) {
fprintf(stderr, "Unable to update config\n"); fprintf(stderr, "Unable to update config\n");
return 1; return 1;
} }
/* Preserve the version unless a new one is given */ /* Preserve the version unless a new one is given */
if (!option.version_specified) if (!sign_option.version_specified)
option.version = preamble->kernel_version; sign_option.version = preamble->kernel_version;
/* Preserve the flags if not specified */ /* Preserve the flags if not specified */
if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) { if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) {
if (option.flags_specified == 0) if (sign_option.flags_specified == 0)
option.flags = preamble->flags; sign_option.flags = preamble->flags;
} }
/* Replace the keyblock if asked */ /* Replace the keyblock if asked */
if (option.keyblock) if (sign_option.keyblock)
keyblock = option.keyblock; keyblock = sign_option.keyblock;
/* Compute the new signature */ /* Compute the new signature */
vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, vblock_data = SignKernelBlob(kblob_data, kblob_size,
option.version, option.kloadaddr, sign_option.padding,
keyblock, option.signprivate, sign_option.version,
option.flags, &vblock_size); sign_option.kloadaddr,
keyblock,
sign_option.signprivate,
sign_option.flags,
&vblock_size);
if (!vblock_data) { if (!vblock_data) {
fprintf(stderr, "Unable to sign kernel blob\n"); fprintf(stderr, "Unable to sign kernel blob\n");
return 1; return 1;
} }
Debug("vblock_size = 0x%" PRIx64 "\n", vblock_size); Debug("vblock_size = 0x%" PRIx64 "\n", vblock_size);
if (option.create_new_outfile) { if (sign_option.create_new_outfile) {
/* Write out what we've been asked for */ /* Write out what we've been asked for */
if (option.vblockonly) if (sign_option.vblockonly)
rv = WriteSomeParts(option.outfile, rv = WriteSomeParts(sign_option.outfile,
vblock_data, vblock_size, vblock_data, vblock_size,
NULL, 0); NULL, 0);
else else
rv = WriteSomeParts(option.outfile, rv = WriteSomeParts(sign_option.outfile,
vblock_data, vblock_size, vblock_data, vblock_size,
kblob_data, kblob_size); kblob_data, kblob_size);
} else { } else {
@@ -374,25 +355,26 @@ int ft_sign_raw_firmware(const char *name, uint8_t *buf, uint32_t len,
VbFirmwarePreambleHeader *preamble; VbFirmwarePreambleHeader *preamble;
int rv; int rv;
body_sig = CalculateSignature(buf, len, option.signprivate); body_sig = CalculateSignature(buf, len, sign_option.signprivate);
if (!body_sig) { if (!body_sig) {
fprintf(stderr, "Error calculating body signature\n"); fprintf(stderr, "Error calculating body signature\n");
return 1; return 1;
} }
preamble = CreateFirmwarePreamble(option.version, preamble = CreateFirmwarePreamble(sign_option.version,
option.kernel_subkey, sign_option.kernel_subkey,
body_sig, body_sig,
option.signprivate, sign_option.signprivate,
option.flags); sign_option.flags);
if (!preamble) { if (!preamble) {
fprintf(stderr, "Error creating firmware preamble.\n"); fprintf(stderr, "Error creating firmware preamble.\n");
free(body_sig); free(body_sig);
return 1; return 1;
} }
rv = WriteSomeParts(option.outfile, rv = WriteSomeParts(sign_option.outfile,
option.keyblock, option.keyblock->key_block_size, sign_option.keyblock,
sign_option.keyblock->key_block_size,
preamble, preamble->preamble_size); preamble, preamble->preamble_size);
free(preamble); free(preamble);
@@ -416,11 +398,11 @@ static int write_new_preamble(struct bios_area_s *vblock,
return 1; return 1;
} }
preamble = CreateFirmwarePreamble(option.version, preamble = CreateFirmwarePreamble(sign_option.version,
option.kernel_subkey, sign_option.kernel_subkey,
body_sig, body_sig,
signkey, signkey,
option.flags); sign_option.flags);
if (!preamble) { if (!preamble) {
fprintf(stderr, "Error creating firmware preamble.\n"); fprintf(stderr, "Error creating firmware preamble.\n");
free(body_sig); free(body_sig);
@@ -444,8 +426,8 @@ static int write_loem(const char *ab, struct bios_area_s *vblock)
char filename[PATH_MAX]; char filename[PATH_MAX];
int n; int n;
n = snprintf(filename, sizeof(filename), "%s/vblock_%s.%s", n = snprintf(filename, sizeof(filename), "%s/vblock_%s.%s",
option.loemdir ? option.loemdir : ".", sign_option.loemdir ? sign_option.loemdir : ".",
ab, option.loemid); ab, sign_option.loemid);
if (n >= sizeof(filename)) { if (n >= sizeof(filename)) {
fprintf(stderr, "LOEM args produce bogus filename\n"); fprintf(stderr, "LOEM args produce bogus filename\n");
return 1; return 1;
@@ -492,29 +474,29 @@ static int sign_bios_at_end(struct sign_state_s *state)
if (fw_a->len != fw_b->len || if (fw_a->len != fw_b->len ||
memcmp(fw_a->buf, fw_b->buf, fw_a->len)) { memcmp(fw_a->buf, fw_b->buf, fw_a->len)) {
/* Yes, must use DEV keys for A */ /* Yes, must use DEV keys for A */
if (!option.devsignprivate || !option.devkeyblock) { if (!sign_option.devsignprivate || !sign_option.devkeyblock) {
fprintf(stderr, fprintf(stderr,
"FW A & B differ. DEV keys are required.\n"); "FW A & B differ. DEV keys are required.\n");
return 1; return 1;
} }
retval |= write_new_preamble(vblock_a, fw_a, retval |= write_new_preamble(vblock_a, fw_a,
option.devsignprivate, sign_option.devsignprivate,
option.devkeyblock); sign_option.devkeyblock);
} else { } else {
retval |= write_new_preamble(vblock_a, fw_a, retval |= write_new_preamble(vblock_a, fw_a,
option.signprivate, sign_option.signprivate,
option.keyblock); sign_option.keyblock);
} }
/* FW B is always normal keys */ /* FW B is always normal keys */
retval |= write_new_preamble(vblock_b, fw_b, retval |= write_new_preamble(vblock_b, fw_b,
option.signprivate, sign_option.signprivate,
option.keyblock); sign_option.keyblock);
if (option.loemid) { if (sign_option.loemid) {
retval |= write_loem("A", vblock_a); retval |= write_loem("A", vblock_a);
retval |= write_loem("B", vblock_b); retval |= write_loem("B", vblock_b);
} }
@@ -717,14 +699,14 @@ static void print_help(int argc, char *argv[])
puts(usage_fw_main); puts(usage_fw_main);
return; return;
case FILE_TYPE_BIOS_IMAGE: case FILE_TYPE_BIOS_IMAGE:
printf(usage_bios, option.version); printf(usage_bios, sign_option.version);
return; return;
case FILE_TYPE_RAW_KERNEL: case FILE_TYPE_RAW_KERNEL:
printf(usage_new_kpart, option.kloadaddr, printf(usage_new_kpart, sign_option.kloadaddr,
option.padding); sign_option.padding);
return; return;
case FILE_TYPE_KERN_PREAMBLE: case FILE_TYPE_KERN_PREAMBLE:
printf(usage_old_kpart, option.padding); printf(usage_old_kpart, sign_option.padding);
return; return;
default: default:
break; break;
@@ -779,7 +761,7 @@ static const struct option long_opts[] = {
{"pem_algo", 1, NULL, OPT_PEM_ALGO}, {"pem_algo", 1, NULL, OPT_PEM_ALGO},
{"pem_external", 1, NULL, OPT_PEM_EXTERNAL}, {"pem_external", 1, NULL, OPT_PEM_EXTERNAL},
{"type", 1, NULL, OPT_TYPE}, {"type", 1, NULL, OPT_TYPE},
{"vblockonly", 0, &option.vblockonly, 1}, {"vblockonly", 0, &sign_option.vblockonly, 1},
{"help", 0, NULL, OPT_HELP}, {"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0}, {NULL, 0, NULL, 0},
}; };
@@ -802,43 +784,43 @@ static int do_sign(int argc, char *argv[])
while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
switch (i) { switch (i) {
case 's': case 's':
option.signprivate = PrivateKeyRead(optarg); sign_option.signprivate = PrivateKeyRead(optarg);
if (!option.signprivate) { if (!sign_option.signprivate) {
fprintf(stderr, "Error reading %s\n", optarg); fprintf(stderr, "Error reading %s\n", optarg);
errorcnt++; errorcnt++;
} }
break; break;
case 'b': case 'b':
option.keyblock = KeyBlockRead(optarg); sign_option.keyblock = KeyBlockRead(optarg);
if (!option.keyblock) { if (!sign_option.keyblock) {
fprintf(stderr, "Error reading %s\n", optarg); fprintf(stderr, "Error reading %s\n", optarg);
errorcnt++; errorcnt++;
} }
break; break;
case 'k': case 'k':
option.kernel_subkey = PublicKeyRead(optarg); sign_option.kernel_subkey = PublicKeyRead(optarg);
if (!option.kernel_subkey) { if (!sign_option.kernel_subkey) {
fprintf(stderr, "Error reading %s\n", optarg); fprintf(stderr, "Error reading %s\n", optarg);
errorcnt++; errorcnt++;
} }
break; break;
case 'S': case 'S':
option.devsignprivate = PrivateKeyRead(optarg); sign_option.devsignprivate = PrivateKeyRead(optarg);
if (!option.devsignprivate) { if (!sign_option.devsignprivate) {
fprintf(stderr, "Error reading %s\n", optarg); fprintf(stderr, "Error reading %s\n", optarg);
errorcnt++; errorcnt++;
} }
break; break;
case 'B': case 'B':
option.devkeyblock = KeyBlockRead(optarg); sign_option.devkeyblock = KeyBlockRead(optarg);
if (!option.devkeyblock) { if (!sign_option.devkeyblock) {
fprintf(stderr, "Error reading %s\n", optarg); fprintf(stderr, "Error reading %s\n", optarg);
errorcnt++; errorcnt++;
} }
break; break;
case 'v': case 'v':
option.version_specified = 1; sign_option.version_specified = 1;
option.version = strtoul(optarg, &e, 0); sign_option.version = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e)) { if (!*optarg || (e && *e)) {
fprintf(stderr, fprintf(stderr,
"Invalid --version \"%s\"\n", optarg); "Invalid --version \"%s\"\n", optarg);
@@ -847,8 +829,8 @@ static int do_sign(int argc, char *argv[])
break; break;
case 'f': case 'f':
option.flags_specified = 1; sign_option.flags_specified = 1;
option.flags = strtoul(optarg, &e, 0); sign_option.flags = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e)) { if (!*optarg || (e && *e)) {
fprintf(stderr, fprintf(stderr,
"Invalid --flags \"%s\"\n", optarg); "Invalid --flags \"%s\"\n", optarg);
@@ -856,13 +838,13 @@ static int do_sign(int argc, char *argv[])
} }
break; break;
case 'd': case 'd':
option.loemdir = optarg; sign_option.loemdir = optarg;
break; break;
case 'l': case 'l':
option.loemid = optarg; sign_option.loemid = optarg;
break; break;
case OPT_FV: case OPT_FV:
option.fv_specified = 1; sign_option.fv_specified = 1;
/* fallthrough */ /* fallthrough */
case OPT_INFILE: case OPT_INFILE:
inout_file_count++; inout_file_count++;
@@ -870,24 +852,24 @@ static int do_sign(int argc, char *argv[])
break; break;
case OPT_OUTFILE: case OPT_OUTFILE:
inout_file_count++; inout_file_count++;
option.outfile = optarg; sign_option.outfile = optarg;
break; break;
case OPT_BOOTLOADER: case OPT_BOOTLOADER:
option.bootloader_data = ReadFile( sign_option.bootloader_data = ReadFile(
optarg, &option.bootloader_size); optarg, &sign_option.bootloader_size);
if (!option.bootloader_data) { if (!sign_option.bootloader_data) {
fprintf(stderr, fprintf(stderr,
"Error reading bootloader file: %s\n", "Error reading bootloader file: %s\n",
strerror(errno)); strerror(errno));
errorcnt++; errorcnt++;
} }
Debug("bootloader file size=0x%" PRIx64 "\n", Debug("bootloader file size=0x%" PRIx64 "\n",
option.bootloader_size); sign_option.bootloader_size);
break; break;
case OPT_CONFIG: case OPT_CONFIG:
option.config_data = ReadConfigFile( sign_option.config_data = ReadConfigFile(
optarg, &option.config_size); optarg, &sign_option.config_size);
if (!option.config_data) { if (!sign_option.config_data) {
fprintf(stderr, fprintf(stderr,
"Error reading config file: %s\n", "Error reading config file: %s\n",
strerror(errno)); strerror(errno));
@@ -898,12 +880,12 @@ static int do_sign(int argc, char *argv[])
/* check the first 3 characters to also match x86_64 */ /* check the first 3 characters to also match x86_64 */
if ((!strncasecmp(optarg, "x86", 3)) || if ((!strncasecmp(optarg, "x86", 3)) ||
(!strcasecmp(optarg, "amd64"))) (!strcasecmp(optarg, "amd64")))
option.arch = ARCH_X86; sign_option.arch = ARCH_X86;
else if ((!strcasecmp(optarg, "arm")) || else if ((!strcasecmp(optarg, "arm")) ||
(!strcasecmp(optarg, "aarch64"))) (!strcasecmp(optarg, "aarch64")))
option.arch = ARCH_ARM; sign_option.arch = ARCH_ARM;
else if (!strcasecmp(optarg, "mips")) else if (!strcasecmp(optarg, "mips"))
option.arch = ARCH_MIPS; sign_option.arch = ARCH_MIPS;
else { else {
fprintf(stderr, fprintf(stderr,
"Unknown architecture: \"%s\"\n", "Unknown architecture: \"%s\"\n",
@@ -912,7 +894,7 @@ static int do_sign(int argc, char *argv[])
} }
break; break;
case OPT_KLOADADDR: case OPT_KLOADADDR:
option.kloadaddr = strtoul(optarg, &e, 0); sign_option.kloadaddr = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e)) { if (!*optarg || (e && *e)) {
fprintf(stderr, fprintf(stderr,
"Invalid --kloadaddr \"%s\"\n", optarg); "Invalid --kloadaddr \"%s\"\n", optarg);
@@ -920,7 +902,7 @@ static int do_sign(int argc, char *argv[])
} }
break; break;
case OPT_PADDING: case OPT_PADDING:
option.padding = strtoul(optarg, &e, 0); sign_option.padding = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e)) { if (!*optarg || (e && *e)) {
fprintf(stderr, fprintf(stderr,
"Invalid --padding \"%s\"\n", optarg); "Invalid --padding \"%s\"\n", optarg);
@@ -928,23 +910,24 @@ static int do_sign(int argc, char *argv[])
} }
break; break;
case OPT_PEM_SIGNPRIV: case OPT_PEM_SIGNPRIV:
option.pem_signpriv = optarg; sign_option.pem_signpriv = optarg;
break; break;
case OPT_PEM_ALGO: case OPT_PEM_ALGO:
option.pem_algo_specified = 1; sign_option.pem_algo_specified = 1;
option.pem_algo = strtoul(optarg, &e, 0); sign_option.pem_algo = strtoul(optarg, &e, 0);
if (!*optarg || (e && *e) || if (!*optarg || (e && *e) ||
(option.pem_algo >= kNumAlgorithms)) { (sign_option.pem_algo >= kNumAlgorithms)) {
fprintf(stderr, fprintf(stderr,
"Invalid --pem_algo \"%s\"\n", optarg); "Invalid --pem_algo \"%s\"\n", optarg);
errorcnt++; errorcnt++;
} }
break; break;
case OPT_PEM_EXTERNAL: case OPT_PEM_EXTERNAL:
option.pem_external = optarg; sign_option.pem_external = optarg;
break; break;
case OPT_TYPE: case OPT_TYPE:
if (!futil_str_to_file_type(optarg, &option.type)) { if (!futil_str_to_file_type(optarg,
&sign_option.type)) {
if (!strcasecmp("help", optarg)) if (!strcasecmp("help", optarg))
print_file_types_and_exit(errorcnt); print_file_types_and_exit(errorcnt);
fprintf(stderr, fprintf(stderr,
@@ -1000,46 +983,48 @@ static int do_sign(int argc, char *argv[])
} }
/* 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 (!option.outfile && argc - optind > 0) { if (!sign_option.outfile && argc - optind > 0) {
inout_file_count++; inout_file_count++;
option.outfile = argv[optind++]; sign_option.outfile = argv[optind++];
} }
/* What are we looking at? */ /* What are we looking at? */
if (option.type == FILE_TYPE_UNKNOWN && if (sign_option.type == FILE_TYPE_UNKNOWN &&
futil_file_type(infile, &option.type)) { futil_file_type(infile, &sign_option.type)) {
errorcnt++; errorcnt++;
goto done; goto done;
} }
/* We may be able to infer the type based on the other args */ /* We may be able to infer the type based on the other args */
if (option.type == FILE_TYPE_UNKNOWN) { if (sign_option.type == FILE_TYPE_UNKNOWN) {
if (option.bootloader_data || option.config_data if (sign_option.bootloader_data || sign_option.config_data
|| option.arch != ARCH_UNSPECIFIED) || sign_option.arch != ARCH_UNSPECIFIED)
option.type = FILE_TYPE_RAW_KERNEL; sign_option.type = FILE_TYPE_RAW_KERNEL;
else if (option.kernel_subkey || option.fv_specified) else if (sign_option.kernel_subkey || sign_option.fv_specified)
option.type = FILE_TYPE_RAW_FIRMWARE; sign_option.type = FILE_TYPE_RAW_FIRMWARE;
} }
Debug("type=%s\n", futil_file_type_name(option.type)); Debug("type=%s\n", futil_file_type_name(sign_option.type));
/* Check the arguments for the type of thing we want to sign */ /* Check the arguments for the type of thing we want to sign */
switch (option.type) { switch (sign_option.type) {
case FILE_TYPE_PUBKEY: case FILE_TYPE_PUBKEY:
option.create_new_outfile = 1; sign_option.create_new_outfile = 1;
if (option.signprivate && option.pem_signpriv) { if (sign_option.signprivate && sign_option.pem_signpriv) {
fprintf(stderr, fprintf(stderr,
"Only one of --signprivate and --pem_signpriv" "Only one of --signprivate and --pem_signpriv"
" can be specified\n"); " can be specified\n");
errorcnt++; errorcnt++;
} }
if ((option.signprivate && option.pem_algo_specified) || if ((sign_option.signprivate &&
(option.pem_signpriv && !option.pem_algo_specified)) { sign_option.pem_algo_specified) ||
(sign_option.pem_signpriv &&
!sign_option.pem_algo_specified)) {
fprintf(stderr, "--pem_algo must be used with" fprintf(stderr, "--pem_algo must be used with"
" --pem_signpriv\n"); " --pem_signpriv\n");
errorcnt++; errorcnt++;
} }
if (option.pem_external && !option.pem_signpriv) { if (sign_option.pem_external && !sign_option.pem_signpriv) {
fprintf(stderr, "--pem_external must be used with" fprintf(stderr, "--pem_external must be used with"
" --pem_signpriv\n"); " --pem_signpriv\n");
errorcnt++; errorcnt++;
@@ -1049,53 +1034,58 @@ static int do_sign(int argc, char *argv[])
break; break;
case FILE_TYPE_BIOS_IMAGE: case FILE_TYPE_BIOS_IMAGE:
case FILE_TYPE_OLD_BIOS_IMAGE: case FILE_TYPE_OLD_BIOS_IMAGE:
errorcnt += no_opt_if(!option.signprivate, "signprivate"); errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
errorcnt += no_opt_if(!option.keyblock, "keyblock"); errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
errorcnt += no_opt_if(!option.kernel_subkey, "kernelkey"); errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey");
break; break;
case FILE_TYPE_KERN_PREAMBLE: case FILE_TYPE_KERN_PREAMBLE:
errorcnt += no_opt_if(!option.signprivate, "signprivate"); errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
if (option.vblockonly || inout_file_count > 1) if (sign_option.vblockonly || inout_file_count > 1)
option.create_new_outfile = 1; sign_option.create_new_outfile = 1;
break; break;
case FILE_TYPE_RAW_FIRMWARE: case FILE_TYPE_RAW_FIRMWARE:
option.create_new_outfile = 1; sign_option.create_new_outfile = 1;
errorcnt += no_opt_if(!option.signprivate, "signprivate"); errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
errorcnt += no_opt_if(!option.keyblock, "keyblock"); errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
errorcnt += no_opt_if(!option.kernel_subkey, "kernelkey"); errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey");
errorcnt += no_opt_if(!option.version_specified, "version"); errorcnt += no_opt_if(!sign_option.version_specified,
"version");
break; break;
case FILE_TYPE_RAW_KERNEL: case FILE_TYPE_RAW_KERNEL:
option.create_new_outfile = 1; sign_option.create_new_outfile = 1;
errorcnt += no_opt_if(!option.signprivate, "signprivate"); errorcnt += no_opt_if(!sign_option.signprivate, "signprivate");
errorcnt += no_opt_if(!option.keyblock, "keyblock"); errorcnt += no_opt_if(!sign_option.keyblock, "keyblock");
errorcnt += no_opt_if(!option.version_specified, "version"); errorcnt += no_opt_if(!sign_option.version_specified,
errorcnt += no_opt_if(!option.bootloader_data, "bootloader"); "version");
errorcnt += no_opt_if(!option.config_data, "config"); errorcnt += no_opt_if(!sign_option.bootloader_data,
errorcnt += no_opt_if(option.arch == ARCH_UNSPECIFIED, "arch"); "bootloader");
errorcnt += no_opt_if(!sign_option.config_data, "config");
errorcnt += no_opt_if(sign_option.arch == ARCH_UNSPECIFIED,
"arch");
break; break;
default: default:
fprintf(stderr, "Unable to sign type %s\n", fprintf(stderr, "Unable to sign type %s\n",
futil_file_type_name(option.type)); futil_file_type_name(sign_option.type));
errorcnt++; errorcnt++;
} }
Debug("infile=%s\n", infile); Debug("infile=%s\n", infile);
Debug("inout_file_count=%d\n", inout_file_count); Debug("inout_file_count=%d\n", inout_file_count);
Debug("option.create_new_outfile=%d\n", option.create_new_outfile); Debug("sign_option.create_new_outfile=%d\n",
sign_option.create_new_outfile);
/* Make sure we have an output file if one is needed */ /* Make sure we have an output file if one is needed */
if (!option.outfile) { if (!sign_option.outfile) {
if (option.create_new_outfile) { if (sign_option.create_new_outfile) {
errorcnt++; errorcnt++;
fprintf(stderr, "Missing output filename\n"); fprintf(stderr, "Missing output filename\n");
goto done; goto done;
} else { } else {
option.outfile = infile; sign_option.outfile = infile;
} }
} }
Debug("option.outfile=%s\n", option.outfile); Debug("sign_option.outfile=%s\n", sign_option.outfile);
if (argc - optind > 0) { if (argc - optind > 0) {
errorcnt++; errorcnt++;
@@ -1105,7 +1095,7 @@ static int do_sign(int argc, char *argv[])
if (errorcnt) if (errorcnt)
goto done; goto done;
if (option.create_new_outfile) { if (sign_option.create_new_outfile) {
/* The input is read-only, the output is write-only. */ /* The input is read-only, the output is write-only. */
mapping = MAP_RO; mapping = MAP_RO;
Debug("open RO %s\n", infile); Debug("open RO %s\n", infile);
@@ -1120,14 +1110,14 @@ static int do_sign(int argc, char *argv[])
/* 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 (inout_file_count > 1)
futil_copy_file_or_die(infile, option.outfile); futil_copy_file_or_die(infile, sign_option.outfile);
Debug("open RW %s\n", option.outfile); Debug("open RW %s\n", sign_option.outfile);
infile = option.outfile; infile = sign_option.outfile;
ifd = open(option.outfile, O_RDWR); ifd = open(sign_option.outfile, O_RDWR);
if (ifd < 0) { if (ifd < 0) {
errorcnt++; errorcnt++;
fprintf(stderr, "Can't open %s for writing: %s\n", fprintf(stderr, "Can't open %s for writing: %s\n",
option.outfile, strerror(errno)); sign_option.outfile, strerror(errno));
goto done; goto done;
} }
} }
@@ -1137,7 +1127,8 @@ static int do_sign(int argc, char *argv[])
goto done; goto done;
} }
errorcnt += futil_file_type_sign(option.type, infile, buf, buf_len); 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, MAP_RW, buf, buf_len);
@@ -1148,12 +1139,12 @@ done:
strerror(errno)); strerror(errno));
} }
if (option.signprivate) if (sign_option.signprivate)
free(option.signprivate); free(sign_option.signprivate);
if (option.keyblock) if (sign_option.keyblock)
free(option.keyblock); free(sign_option.keyblock);
if (option.kernel_subkey) if (sign_option.kernel_subkey)
free(option.kernel_subkey); free(sign_option.kernel_subkey);
if (errorcnt) if (errorcnt)
fprintf(stderr, "Use --help for usage instructions\n"); fprintf(stderr, "Use --help for usage instructions\n");

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2015 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* We centralize option parsing but may split operations into multiple files,
* so let's declare the option structures in a single place (here).
*/
#ifndef VBOOT_REFERENCE_FUTILITY_OPTIONS_H_
#define VBOOT_REFERENCE_FUTILITY_OPTIONS_H_
#include <stdint.h>
#include "vboot_common.h"
struct show_option_s {
VbPublicKey *k;
uint8_t *fv;
uint64_t fv_size;
uint32_t padding;
int strict;
int t_flag;
enum futil_file_type type;
};
extern struct show_option_s show_option;
struct sign_option_s {
VbPrivateKey *signprivate;
VbKeyBlockHeader *keyblock;
VbPublicKey *kernel_subkey;
VbPrivateKey *devsignprivate;
VbKeyBlockHeader *devkeyblock;
uint32_t version;
int version_specified;
uint32_t flags;
int flags_specified;
char *loemdir;
char *loemid;
uint8_t *bootloader_data;
uint64_t bootloader_size;
uint8_t *config_data;
uint64_t config_size;
enum arch_t arch;
int fv_specified;
uint32_t kloadaddr;
uint32_t padding;
int vblockonly;
char *outfile;
int create_new_outfile;
char *pem_signpriv;
int pem_algo_specified;
uint32_t pem_algo;
char *pem_external;
enum futil_file_type type;
};
extern struct sign_option_s sign_option;
#endif /* VBOOT_REFERENCE_FUTILITY_OPTIONS_H_ */