summaryrefslogtreecommitdiff
path: root/futility/cmd_sign.c
diff options
context:
space:
mode:
Diffstat (limited to 'futility/cmd_sign.c')
-rw-r--r--futility/cmd_sign.c162
1 files changed, 131 insertions, 31 deletions
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index 9ec99f6f..3152091c 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -27,6 +27,8 @@
#include "kernel_blob.h"
#include "util_misc.h"
#include "vb1_helper.h"
+#include "vb2_common.h"
+#include "host_key2.h"
#include "vboot_common.h"
/* Options */
@@ -36,6 +38,11 @@ struct sign_option_s sign_option = {
.kloadaddr = CROS_32BIT_ENTRY_ADDR,
.padding = 65536,
.type = FILE_TYPE_UNKNOWN,
+ .hash_alg = VB2_HASH_SHA256, /* default */
+ .ro_size = 0xffffffff,
+ .rw_size = 0xffffffff,
+ .ro_offset = 0xffffffff,
+ .rw_offset = 0xffffffff,
};
/* Helper to complain about invalid args. Returns num errors discovered */
@@ -406,12 +413,62 @@ static void print_help_kern_preamble(int argc, char *argv[])
printf(usage_old_kpart, sign_option.padding);
}
+static void print_help_usbpd1(int argc, char *argv[])
+{
+ struct vb2_text_vs_enum *entry;
+
+ printf("\n"
+ "Usage: " MYNAME " %s --type %s [options] INFILE [OUTFILE]\n"
+ "\n"
+ "This signs a %s.\n"
+ "\n"
+ "The INPUT is assumed to consist of equal-sized RO and RW"
+ " sections,\n"
+ "with the public key at the end of of the RO section and the"
+ " signature\n"
+ "at the end of the RW section (both in an opaque binary"
+ " format).\n"
+ "Signing the image will update both binary blobs, so both"
+ " public and\n"
+ "private keys are required.\n"
+ "\n"
+ "The signing key is specified with:\n"
+ "\n"
+ " --pem "
+ "FILE Signing keypair in PEM format\n"
+ "\n"
+ " --hash_alg "
+ "NUM Hash algorithm to use:\n",
+ argv[0],
+ futil_file_type_name(FILE_TYPE_USBPD1),
+ futil_file_type_desc(FILE_TYPE_USBPD1));
+ for (entry = vb2_text_vs_hash; entry->name; entry++)
+ printf(" %d / %s%s\n",
+ entry->num, entry->name,
+ entry->num == VB2_HASH_SHA256 ? " (default)" : "");
+ printf("\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"
+ " --ro_size NUM"
+ " Size of the RO section (default half)\n"
+ " --rw_size NUM"
+ " Size of the RW section (default half)\n"
+ " --ro_offset NUM"
+ " Start of the RO section (default 0)\n"
+ " --rw_offset NUM"
+ " Start of the RW section (default half)\n"
+ "\n");
+}
+
static void (*help_type[NUM_FILE_TYPES])(int argc, char *argv[]) = {
[FILE_TYPE_PUBKEY] = &print_help_pubkey,
[FILE_TYPE_RAW_FIRMWARE] = &print_help_raw_firmware,
[FILE_TYPE_BIOS_IMAGE] = &print_help_bios_image,
[FILE_TYPE_RAW_KERNEL] = &print_help_raw_kernel,
[FILE_TYPE_KERN_PREAMBLE] = &print_help_kern_preamble,
+ [FILE_TYPE_USBPD1] = &print_help_usbpd1,
};
static const char usage_default[] = "\n"
@@ -465,6 +522,11 @@ enum no_short_opts {
OPT_PEM_ALGO,
OPT_PEM_EXTERNAL,
OPT_TYPE,
+ OPT_HASH_ALG,
+ OPT_RO_SIZE,
+ OPT_RW_SIZE,
+ OPT_RO_OFFSET,
+ OPT_RW_OFFSET,
OPT_HELP,
};
@@ -490,15 +552,34 @@ static const struct option long_opts[] = {
{"kloadaddr", 1, NULL, OPT_KLOADADDR},
{"pad", 1, NULL, OPT_PADDING},
{"pem_signpriv", 1, NULL, OPT_PEM_SIGNPRIV},
+ {"pem", 1, NULL, OPT_PEM_SIGNPRIV}, /* alias */
{"pem_algo", 1, NULL, OPT_PEM_ALGO},
{"pem_external", 1, NULL, OPT_PEM_EXTERNAL},
{"type", 1, NULL, OPT_TYPE},
{"vblockonly", 0, &sign_option.vblockonly, 1},
+ {"hash_alg", 1, NULL, OPT_HASH_ALG},
+ {"ro_size", 1, NULL, OPT_RO_SIZE},
+ {"rw_size", 1, NULL, OPT_RW_SIZE},
+ {"ro_offset", 1, NULL, OPT_RO_OFFSET},
+ {"rw_offset", 1, NULL, OPT_RW_OFFSET},
{"help", 0, NULL, OPT_HELP},
{NULL, 0, NULL, 0},
};
static char *short_opts = ":s:b:k:S:B:v:f:d:l:";
+/* Return zero on success */
+static int parse_number_opt(const char *arg, const char *name, uint32_t *dest)
+{
+ char *e;
+ uint32_t val = strtoul(arg, &e, 0);
+ if (!*arg || (e && *e)) {
+ fprintf(stderr, "Invalid --%s \"%s\"\n", name, arg);
+ return 1;
+ }
+ *dest = val;
+ return 0;
+}
+
static int do_sign(int argc, char *argv[])
{
char *infile = 0;
@@ -511,9 +592,11 @@ static int do_sign(int argc, char *argv[])
int inout_file_count = 0;
int mapping;
int helpind = 0;
+ int longindex;
opterr = 0; /* quiet, you */
- while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
+ while ((i = getopt_long(argc, argv, short_opts, long_opts,
+ &longindex)) != -1) {
switch (i) {
case 's':
sign_option.signprivate = PrivateKeyRead(optarg);
@@ -562,12 +645,8 @@ static int do_sign(int argc, char *argv[])
case 'f':
sign_option.flags_specified = 1;
- sign_option.flags = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr,
- "Invalid --flags \"%s\"\n", optarg);
- errorcnt++;
- }
+ errorcnt += parse_number_opt(optarg, "flags",
+ &sign_option.flags);
break;
case 'd':
sign_option.loemdir = optarg;
@@ -626,20 +705,28 @@ static int do_sign(int argc, char *argv[])
}
break;
case OPT_KLOADADDR:
- sign_option.kloadaddr = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr,
- "Invalid --kloadaddr \"%s\"\n", optarg);
- errorcnt++;
- }
+ errorcnt += parse_number_opt(optarg, "kloadaddr",
+ &sign_option.kloadaddr);
break;
case OPT_PADDING:
- sign_option.padding = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr,
- "Invalid --padding \"%s\"\n", optarg);
- errorcnt++;
- }
+ errorcnt += parse_number_opt(optarg, "padding",
+ &sign_option.padding);
+ break;
+ case OPT_RO_SIZE:
+ errorcnt += parse_number_opt(optarg, "ro_size",
+ &sign_option.ro_size);
+ break;
+ case OPT_RW_SIZE:
+ errorcnt += parse_number_opt(optarg, "rw_size",
+ &sign_option.rw_size);
+ break;
+ case OPT_RO_OFFSET:
+ errorcnt += parse_number_opt(optarg, "ro_offset",
+ &sign_option.ro_offset);
+ break;
+ case OPT_RW_OFFSET:
+ errorcnt += parse_number_opt(optarg, "rw_offset",
+ &sign_option.rw_offset);
break;
case OPT_PEM_SIGNPRIV:
sign_option.pem_signpriv = optarg;
@@ -654,6 +741,14 @@ static int do_sign(int argc, char *argv[])
errorcnt++;
}
break;
+ case OPT_HASH_ALG:
+ if (!vb2_lookup_hash_alg(optarg,
+ &sign_option.hash_alg)) {
+ fprintf(stderr,
+ "invalid hash_alg \"%s\"\n", optarg);
+ errorcnt++;
+ }
+ break;
case OPT_PEM_EXTERNAL:
sign_option.pem_external = optarg;
break;
@@ -795,6 +890,11 @@ static int do_sign(int argc, char *argv[])
errorcnt += no_opt_if(sign_option.arch == ARCH_UNSPECIFIED,
"arch");
break;
+ case FILE_TYPE_USBPD1:
+ errorcnt += no_opt_if(!sign_option.pem_signpriv, "pem");
+ errorcnt += no_opt_if(sign_option.hash_alg == VB2_HASH_INVALID,
+ "hash_alg");
+ break;
default:
/* Anything else we don't care */
break;
@@ -839,18 +939,18 @@ static int do_sign(int argc, char *argv[])
}
} else {
/* We'll read-modify-write the output file */
- mapping = MAP_RW;
- if (inout_file_count > 1)
- futil_copy_file_or_die(infile, sign_option.outfile);
- Debug("open RW %s\n", sign_option.outfile);
- infile = sign_option.outfile;
- ifd = open(sign_option.outfile, O_RDWR);
- if (ifd < 0) {
- errorcnt++;
- fprintf(stderr, "Can't open %s for writing: %s\n",
- sign_option.outfile, strerror(errno));
- goto done;
- }
+ mapping = MAP_RW;
+ if (inout_file_count > 1)
+ futil_copy_file_or_die(infile, sign_option.outfile);
+ Debug("open RW %s\n", sign_option.outfile);
+ infile = sign_option.outfile;
+ ifd = open(sign_option.outfile, O_RDWR);
+ if (ifd < 0) {
+ errorcnt++;
+ fprintf(stderr, "Can't open %s for writing: %s\n",
+ sign_option.outfile, strerror(errno));
+ goto done;
+ }
}
if (0 != futil_map_file(ifd, mapping, &buf, &buf_len)) {