diff options
author | Bill Richardson <wfrichar@chromium.org> | 2015-10-15 00:23:18 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2015-10-15 19:57:13 -0700 |
commit | 02ac2885fd797fba7f12ef040f0eb041dda7af20 (patch) | |
tree | 8c8386e3fc07bb5f7cc8c5c485cf10a58dec1340 /futility/cmd_sign.c | |
parent | df0e1a391fa7b8d7bdb31f9623fbbcbb158cd2ad (diff) | |
download | vboot-02ac2885fd797fba7f12ef040f0eb041dda7af20.tar.gz |
futility: Revised support for RO+RW firmware
The "rwsig" type is used for independent device firmware (not
Chromebook BIOS) that need to verify themselves instead of using
software sync.
The expected use case is that a RO firmware contains a
vb2_public_key struct along with an FMAP or other pointers to a
slot for RW firmware. The RW firmware slot reserves room for a
vb2_signature struct.
This CL changes the args and behavior of the rwsig type, so that
the RW firmware can be [re]signed independently of the rest of
the image.
BUG=chrome-os-partner:46254
BRANCH=smaug,ToT
TEST=make runtests, manual
Create a keypair:
futility create --desc "Key One" tests/testkeys/key_rsa2048.pem foo
Sign a RW binary and build a complete image out of the parts:
futility sign --type rwsig --prikey foo.vbprik2 rw.bin sig.bin
dd if=/dev/zero bs=65536 count=1 of=image.bin
dd if=rw.bin of=image.bin conv=notrunc
dd if=sig.bin bs=$((65536 - 1024)) seek=1 of=image.bin conv=notrunc
Verify both the separate parts and the combined image:
futility show --type rwsig --pubkey foo.vbpubk2 rw.bin sig.bin
futility show --type rwsig --pubkey foo.vbpubk2 image.bin
Re-sign the combined image with a different keypair:
futility create --desc "Key Two" tests/testkeys/key_rsa1024.pem bar
futility sign --type rwsig --prikey bar.vbprik2 image.bin
Now the first key no longer verifies:
futility show --type rwsig --pubkey foo.vbpubk2 image.bin
But the second key does:
futility show --type rwsig --pubkey bar.vbpubk2 image.bin
Change-Id: Ifdddab08f218f506eb1dce28851b153d70140a7b
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/305980
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'futility/cmd_sign.c')
-rw-r--r-- | futility/cmd_sign.c | 100 |
1 files changed, 42 insertions, 58 deletions
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c index e6184f43..c27f71e8 100644 --- a/futility/cmd_sign.c +++ b/futility/cmd_sign.c @@ -43,8 +43,7 @@ struct sign_option_s sign_option = { .rw_size = 0xffffffff, .ro_offset = 0xffffffff, .rw_offset = 0xffffffff, - .pkey_offset = 0xffffffff, - .sig_offset = 0xffffffff, + .sig_size = 1024, }; /* Helper to complain about invalid args. Returns num errors discovered */ @@ -424,7 +423,7 @@ static void print_help_usbpd1(int argc, char *argv[]) "\n" "This signs a %s.\n" "\n" - "The INPUT is assumed to consist of equal-sized RO and RW" + "The INFILE is assumed to consist of equal-sized RO and RW" " sections,\n" "with the public key at the end of of the RO section and the" " signature\n" @@ -464,7 +463,6 @@ static void print_help_usbpd1(int argc, char *argv[]) "\n"); } -/* The rwsig help is the same as the usbpd1 help, for now anyway. */ static void print_help_rwsig(int argc, char *argv[]) { printf("\n" @@ -472,35 +470,30 @@ static void print_help_rwsig(int argc, char *argv[]) "\n" "This signs a %s.\n" "\n" - "The INPUT is assumed to consist of equal-sized RO and RW" - " sections.\n" - "Signing the RW image will put the signature in the RW half." - " If the public\n" - "key is provided, it will be copied to the RO half.\n" + "The INFILE is a binary blob of arbitrary size." + " It is signed using the\n" + "private key and the vb2_signature blob emitted.\n" "\n" - "Options:\n" - "\n" - " --prikey FILE.vbprik2" - " Private key in vb2 format\n" - " --pubkey FILE.vbpubk2" - " Public key in vb2 format\n" + "If no OUTFILE is specified, the INFILE should contain" + " an existing\n" + "vb2_signature blob near its end. The data_size from that" + " signature is\n" + "used to re-sign a portion of the INFILE, and the old" + " signature blob is\n" + "replaced.\n" "\n" - "The size and offset assumptions can be overridden. " - "All numbers are in bytes.\n" - "Specify a size of 0 to ignore that section.\n" + "Options:\n" "\n" - " --rw_size NUM" - " Size of the RW section (default half)\n" - " --rw_offset NUM" - " Start of the RW section (default half)\n" - " --sig_offset NUM" - " Where to place the signature (default is\n" - " " - " near the end of the RW image)\n" - " --pkey_offset NUM" - " Where to place the public key (default is\n" - " " - " near the end of the RO image)\n" + " --prikey FILE.vbprik2 " + "Private key in vb2 format (required)\n" + " --sig_size NUM " + "Offset from the end of INFILE where the\n" + " " + "signature blob should be located\n" + " " + "(default 1024 bytes)\n" + " --data_size NUM " + "Number of bytes of INFILE to sign\n" "\n", argv[0], futil_file_type_name(FILE_TYPE_RWSIG), @@ -529,7 +522,7 @@ static const char usage_default[] = "\n" " raw linux kernel (vmlinuz) kernel partition image\n" " kernel partition (/dev/sda2) same, or signed in-place\n" " usbpd1 firmware image same, or signed in-place\n" - " RO+RW firmware image same, or signed in-place\n" + " RW device image same, or signed in-place\n" "\n" "For more information, use \"" MYNAME " help %s TYPE\", where\n" "TYPE is one of:\n\n"; @@ -575,10 +568,9 @@ enum no_short_opts { OPT_RW_SIZE, OPT_RO_OFFSET, OPT_RW_OFFSET, - OPT_PKEY_OFFSET, - OPT_SIG_OFFSET, + OPT_DATA_SIZE, + OPT_SIG_SIZE, OPT_PRIKEY, - OPT_PUBKEY, OPT_HELP, }; @@ -614,11 +606,10 @@ static const struct option long_opts[] = { {"rw_size", 1, NULL, OPT_RW_SIZE}, {"ro_offset", 1, NULL, OPT_RO_OFFSET}, {"rw_offset", 1, NULL, OPT_RW_OFFSET}, - {"pkey_offset", 1, NULL, OPT_PKEY_OFFSET}, - {"sig_offset", 1, NULL, OPT_SIG_OFFSET}, + {"data_size", 1, NULL, OPT_DATA_SIZE}, + {"sig_size", 1, NULL, OPT_SIG_SIZE}, {"prikey", 1, NULL, OPT_PRIKEY}, {"privkey", 1, NULL, OPT_PRIKEY}, /* alias */ - {"pubkey", 1, NULL, OPT_PUBKEY}, {"help", 0, NULL, OPT_HELP}, {NULL, 0, NULL, 0}, }; @@ -646,7 +637,6 @@ static int do_sign(int argc, char *argv[]) uint8_t *buf; uint32_t buf_len; char *e = 0; - int inout_file_count = 0; int mapping; int helpind = 0; int longindex; @@ -715,11 +705,11 @@ static int do_sign(int argc, char *argv[]) sign_option.fv_specified = 1; /* fallthrough */ case OPT_INFILE: - inout_file_count++; + sign_option.inout_file_count++; infile = optarg; break; case OPT_OUTFILE: - inout_file_count++; + sign_option.inout_file_count++; sign_option.outfile = optarg; break; case OPT_BOOTLOADER: @@ -785,13 +775,13 @@ static int do_sign(int argc, char *argv[]) errorcnt += parse_number_opt(optarg, "rw_offset", &sign_option.rw_offset); break; - case OPT_PKEY_OFFSET: - errorcnt += parse_number_opt(optarg, "pkey_offset", - &sign_option.pkey_offset); + case OPT_DATA_SIZE: + errorcnt += parse_number_opt(optarg, "data_size", + &sign_option.data_size); break; - case OPT_SIG_OFFSET: - errorcnt += parse_number_opt(optarg, "sig_offset", - &sign_option.sig_offset); + case OPT_SIG_SIZE: + errorcnt += parse_number_opt(optarg, "sig_size", + &sign_option.sig_size); break; case OPT_PEM_SIGNPRIV: sign_option.pem_signpriv = optarg; @@ -834,12 +824,6 @@ static int do_sign(int argc, char *argv[]) errorcnt++; } break; - case OPT_PUBKEY: - if (vb2_packed_key_read(&sign_option.pkey, optarg)) { - fprintf(stderr, "Error reading %s\n", optarg); - errorcnt++; - } - break; case OPT_HELP: helpind = optind - 1; break; @@ -882,14 +866,14 @@ static int do_sign(int argc, char *argv[]) fprintf(stderr, "ERROR: missing input filename\n"); goto done; } else { - inout_file_count++; + sign_option.inout_file_count++; infile = argv[optind++]; } } /* Look for an output file if we don't have one, just in case. */ if (!sign_option.outfile && argc - optind > 0) { - inout_file_count++; + sign_option.inout_file_count++; sign_option.outfile = argv[optind++]; } @@ -945,7 +929,7 @@ static int do_sign(int argc, char *argv[]) break; case FILE_TYPE_KERN_PREAMBLE: errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); - if (sign_option.vblockonly || inout_file_count > 1) + if (sign_option.vblockonly || sign_option.inout_file_count > 1) sign_option.create_new_outfile = 1; break; case FILE_TYPE_RAW_FIRMWARE: @@ -982,7 +966,7 @@ static int do_sign(int argc, char *argv[]) } Debug("infile=%s\n", infile); - Debug("inout_file_count=%d\n", inout_file_count); + Debug("sign_option.inout_file_count=%d\n", sign_option.inout_file_count); Debug("sign_option.create_new_outfile=%d\n", sign_option.create_new_outfile); @@ -1021,7 +1005,7 @@ static int do_sign(int argc, char *argv[]) } else { /* We'll read-modify-write the output file */ mapping = MAP_RW; - if (inout_file_count > 1) + if (sign_option.inout_file_count > 1) futil_copy_file_or_die(infile, sign_option.outfile); Debug("open RW %s\n", sign_option.outfile); infile = sign_option.outfile; @@ -1042,7 +1026,7 @@ static int do_sign(int argc, char *argv[]) errorcnt += futil_file_type_sign(sign_option.type, infile, buf, buf_len); - errorcnt += futil_unmap_file(ifd, MAP_RW, buf, buf_len); + errorcnt += futil_unmap_file(ifd, mapping, buf, buf_len); done: if (ifd >= 0 && close(ifd)) { |