mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 18:25:10 +00:00
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:
committed by
ChromeOS Commit Bot
parent
453ecd1956
commit
1e35c3a511
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
59
futility/futility_options.h
Normal file
59
futility/futility_options.h
Normal 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_ */
|
||||||
Reference in New Issue
Block a user