From 3d25d2b4ba7886244176aa8c429fdac2acf7db3e Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Thu, 31 Aug 2017 10:12:40 -0700 Subject: futility: Make rwsig sign command produce EC_RW image This change makes futility write out a EC_RW image to the filesystem. It also allows the command to run without '--prikey' option. When a private key isn't provided, the command copies the previous signature. This can be used to extract EC_RW without changing the key or the signature. Since data only mode doesn't have a previous signature, the command returns error if '--prikey' isn't specified (as done before). BUG=b:65027647 BRANCH=none TEST=Run futility as follows futility sign --type rwsig ec.RW.flat ec.RW.sig (Missing key error, expected) futility sign --type rwsig ec.bin (EC_RW.bin is produced) futility sign --type rwsig EC_RW.bin futility sign --type rwsig --prikey key.vbprik2 ec.RW.flat ec.RW.sig futility sign --type rwsig --prikey key.vbprik2 ec.bin (EC_RW.bin is produced) futility sign --type rwsig --prikey key.vbprik2 EC_RW.bin make runfutiltests Change-Id: I8c1e0cef147967cfd6d28aa7272b88c03e109e0d Signed-off-by: Daisuke Nojiri Reviewed-on: https://chromium-review.googlesource.com/647804 Reviewed-by: Randall Spangler --- futility/cmd_sign.c | 14 ++++++++++---- futility/file_type_rwsig.c | 43 ++++++++++++++++++++++++++++++++---------- tests/futility/data/EC_RW.bin | Bin 0 -> 65536 bytes tests/futility/test_rwsig.sh | 11 +++++++++-- 4 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 tests/futility/data/EC_RW.bin diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c index 8599c74c..7a53887f 100644 --- a/futility/cmd_sign.c +++ b/futility/cmd_sign.c @@ -495,12 +495,16 @@ static void print_help_rwsig(int argc, char *argv[]) "If INFILE contains an FMAP, RW and signatures offsets are read from\n" "FMAP. These regions must be named EC_RW and SIG_RW respectively.\n" "If a public key is found in the region named KEY_RO, it will be replaced\n" - "in the RO image.\n" + "in the RO image. This mode also produces EC_RW.bin which is a EC_RW\n" + "region image (same as the input file for 'Data + Signature mode').\n" "\n" "Options:\n" "\n" - " --prikey FILE.vbprik2 Private key in vb2 format (required)\n" - " --version NUM Public key version if we are replacing" + " --prikey FILE.vbprik2 Private key in vb2 format. Required\n" + " if INFILE is a binary blob. If not\n" + " provided, previous signature is copied\n" + " and a public key won't be replaced.\n" + " --version NUM Public key version if we are replacing\n" " the key in INFILE (default: 1)\n" " --sig_size NUM Offset from the end of INFILE where the\n" " signature blob should be located, if\n" @@ -972,7 +976,9 @@ static int do_sign(int argc, char *argv[]) "hash_alg"); break; case FILE_TYPE_RWSIG: - errorcnt += no_opt_if(!sign_option.prikey, "prikey"); + if (sign_option.inout_file_count > 1) + /* Signing raw data. No signature pre-exists. */ + errorcnt += no_opt_if(!sign_option.prikey, "prikey"); break; default: /* Anything else we don't care */ diff --git a/futility/file_type_rwsig.c b/futility/file_type_rwsig.c index 1323da41..ebedf651 100644 --- a/futility/file_type_rwsig.c +++ b/futility/file_type_rwsig.c @@ -28,10 +28,12 @@ #include "vb21_common.h" #include "host_common.h" #include "host_key2.h" +#include "host_misc.h" #include "host_signature2.h" #include "util_misc.h" #define SIGNATURE_RSVD_SIZE 1024 +#define EC_RW_FILENAME "EC_RW.bin" static inline void vb2_print_bytes(const void *ptr, uint32_t len) { @@ -215,14 +217,13 @@ int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin) int retval = 1; FmapHeader *fmap = NULL; FmapAreaHeader *fmaparea; + const struct vb21_signature *old_sig = 0; Debug("%s(): name %s\n", __func__, name); Debug("%s(): len 0x%08x (%d)\n", __func__, len, len); /* If we don't have a distinct OUTFILE, look for an existing sig */ if (sign_option.inout_file_count < 2) { - const struct vb21_signature *old_sig; - fmap = fmap_find(buf, len); if (fmap) { @@ -284,12 +285,26 @@ int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin) data_size = sign_option.data_size; /* Sign the blob */ - r = vb21_sign_data(&tmp_sig, data, data_size, sign_option.prikey, 0); - if (r) { - fprintf(stderr, - "Unable to sign data (error 0x%08x, if that helps)\n", - r); - goto done; + if (sign_option.prikey) { + r = vb21_sign_data(&tmp_sig, + data, data_size, sign_option.prikey, 0); + if (r) { + fprintf(stderr, + "Unable to sign data (error 0x%08x)\n", r); + goto done; + } + } else { + Debug("Private key not provided. Copying previous signature\n"); + if (!old_sig) { + /* This isn't necessary because no prikey mode runs only + * for fmap input or RW input */ + fprintf(stderr, "Previous signature not found.\n"); + goto done; + } + tmp_sig = calloc(1, old_sig->c.total_size); + if (!tmp_sig) + goto done; + memcpy(tmp_sig, old_sig, old_sig->c.total_size); } if (sign_option.inout_file_count < 2) { @@ -301,6 +316,13 @@ int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin) } memset(buf + len - sig_size, 0xff, sig_size); memcpy(buf + len - sig_size, tmp_sig, tmp_sig->c.total_size); + if (fmap) { + Debug("Writing %s (size=%d)\n", + EC_RW_FILENAME, fmaparea->area_size); + if (vb2_write_file(EC_RW_FILENAME, + data, fmaparea->area_size)) + goto done; + } } else { /* Write the signature to a new file */ r = vb21_write_object(sign_option.outfile, tmp_sig); @@ -311,8 +333,9 @@ int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin) } } - /* For full images, let's replace the public key in RO. */ - if (fmap) { + /* For full images, let's replace the public key in RO. If prikey is + * not provided, skip it. */ + if (fmap && sign_option.prikey) { uint8_t *new_pubkey; uint8_t *pubkey_buf = 0; diff --git a/tests/futility/data/EC_RW.bin b/tests/futility/data/EC_RW.bin new file mode 100644 index 00000000..4f5a46a5 Binary files /dev/null and b/tests/futility/data/EC_RW.bin differ diff --git a/tests/futility/test_rwsig.sh b/tests/futility/test_rwsig.sh index 846074d9..6a28f029 100755 --- a/tests/futility/test_rwsig.sh +++ b/tests/futility/test_rwsig.sh @@ -14,16 +14,20 @@ TESTKEYS=${SRCDIR}/tests/testkeys SIGS="1024 2048 2048_exp3 3072_exp3 4096 8192" HASHES="SHA1 SHA256 SHA512" +EC_RW="EC_RW.bin" set -o pipefail +infile=${DATADIR}/hammer_dev.bin +# Signing without private key should extract EC_RW.bin +${FUTILITY} sign --type rwsig --version 2 ${infile} +cmp ${EC_RW} ${DATADIR}/${EC_RW} + for s in $SIGS; do echo -n "$s " 1>&3 for h in $HASHES; do pemfile=${TESTKEYS}/key_rsa${s}.pem - outfile=${TMP}.${s}_${h}.new - infile=${DATADIR}/hammer_dev.bin outkeys=${TMP}.${s}_${h} outfile=${TMP}.${s}_${h}.bin @@ -41,8 +45,11 @@ for s in $SIGS; do cp ${infile} ${outfile} + # Sign ec.bin with a new private key ${FUTILITY} sign --type rwsig --prikey ${outkeys}.vbprik2 \ --version 2 ${outfile} + # Check EC_RW.bin is produced + [[ -e ${EC_RW} ]] ${FUTILITY} show --type rwsig --pubkey ${outkeys}.vbpubk2 ${outfile} ${FUTILITY} show --type rwsig ${outfile} -- cgit v1.2.1