diff options
22 files changed, 569 insertions, 49 deletions
@@ -626,6 +626,7 @@ FUTIL_SRCS = \ futility/cmd_vbutil_keyblock.c \ futility/file_type.c \ futility/file_type_bios.c \ + futility/file_type_usbpd1.c \ futility/vb1_helper.c \ futility/vb2_helper.c diff --git a/futility/cmd_create.c b/futility/cmd_create.c index c919eab3..e3fafd30 100644 --- a/futility/cmd_create.c +++ b/futility/cmd_create.c @@ -23,6 +23,7 @@ #include "host_misc2.h" #include "futility.h" +#include "futility_options.h" /* Command line options */ enum { @@ -283,7 +284,6 @@ static int do_create(int argc, char *argv[]) int errorcnt = 0; char *e, *s; int i, r, len, remove_ext = 0; - const struct vb2_text_vs_enum *entry; while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { switch (i) { @@ -311,28 +311,13 @@ static int do_create(int argc, char *argv[]) break; case OPT_HASH_ALG: - /* try string first */ - entry = vb2_lookup_by_name(vb2_text_vs_hash, optarg); - if (entry) { - opt_hash_alg = entry->num; - break; - } - /* fine, try number */ - opt_hash_alg = strtoul(optarg, &e, 0); - if (!*optarg || (e && *e)) { + if (!vb2_lookup_hash_alg(optarg, &opt_hash_alg)) { fprintf(stderr, "invalid hash_alg \"%s\"\n", optarg); errorcnt++; - break; - } - if (!vb2_lookup_by_num(vb2_text_vs_hash, - opt_hash_alg)) { - fprintf(stderr, - "Hash algorithm %d is unsupported\n", - opt_hash_alg); - errorcnt++; } break; + case OPT_HELP: print_help(argc, argv); return !!errorcnt; 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)) { diff --git a/futility/file_type.inc b/futility/file_type.inc index 7d40d45c..4014c0b4 100644 --- a/futility/file_type.inc +++ b/futility/file_type.inc @@ -71,3 +71,9 @@ FILE_TYPE(CHROMIUMOS_DISK, "disk_img", "chromiumos disk image", NONE, NONE, NONE) + +/* Firmware for Samus' USB Type-C power adapters */ +FILE_TYPE(USBPD1, "usbpd1", "USB-PD charger image (v1.0)", + NONE, + NONE, + S_(ft_sign_usbpd1)) diff --git a/futility/file_type_usbpd1.c b/futility/file_type_usbpd1.c new file mode 100644 index 00000000..7230b0ca --- /dev/null +++ b/futility/file_type_usbpd1.c @@ -0,0 +1,227 @@ +/* + * 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. + */ + +/* + * The USB Type-C chargers released with Samus ("Pixel (2015)") have upgradable + * firmware. Due to space considerations, we don't have room for handy things + * like an FMAP or headers for the signatures. Accordingly, all the normally + * variable factors (image size, signature algorithms, etc.) are hard coded + * and the image itself just looks like a bunch of random numbers. + * + * This file handles those images, but PLEASE don't use it as a template for + * new devices. + */ + +#include <stdint.h> +#include <stdio.h> +#include <unistd.h> + +#include "2sysincludes.h" +#include "2common.h" +#include "2rsa.h" +#include "file_type.h" +#include "futility.h" +#include "futility_options.h" +#include "vb2_common.h" +#include "host_common.h" +#include "host_key2.h" +#include "host_signature2.h" +#include "util_misc.h" + +int ft_sign_usbpd1(const char *name, uint8_t *buf, uint32_t len, void *data) +{ + struct vb2_private_key *key_ptr = 0; + struct vb2_signature *sig_ptr = 0; + uint8_t *keyb_data = 0; + uint32_t keyb_size; + int retval = 1; + uint32_t sig_size; + uint32_t sig_offset; + uint32_t pub_size; + uint32_t pub_offset; + uint32_t ro_size; + uint32_t rw_size; + uint32_t ro_offset; + uint32_t rw_offset; + uint32_t r; + + Debug("%s(): name %s\n", __func__, name); + Debug("%s(): len 0x%08x (%d)\n", __func__, len, len); + + /* + * Check for size args. Note that we're NOT worrying about rollover, + * overlapping regions, out of bounds, etc. + */ + ro_offset = 0; + ro_size = rw_size = rw_offset = len / 2; + + /* Override some stuff? */ + if (sign_option.ro_size != 0xffffffff) + ro_size = sign_option.ro_size; + if (sign_option.rw_size != 0xffffffff) + rw_size = sign_option.rw_size; + + Debug("ro_size 0x%08x\n", ro_size); + Debug("ro_offset 0x%08x\n", ro_offset); + + /* If RO is missing, the whole thing must be RW */ + if (!ro_size) { + rw_size = len; + rw_offset = 0; + } + + /* Unless that's overridden too */ + if (sign_option.ro_offset != 0xffffffff) + ro_offset = sign_option.ro_offset; + if (sign_option.rw_offset != 0xffffffff) + rw_offset = sign_option.rw_offset; + + Debug("rw_size 0x%08x\n", rw_size); + Debug("rw_offset 0x%08x\n", rw_offset); + + /* Read the signing keypair file */ + if (vb2_private_key_read_pem(&key_ptr, sign_option.pem_signpriv)) { + fprintf(stderr, "Unable to read keypair from %s\n", + sign_option.pem_signpriv); + goto done; + } + + /* Set the algs */ + key_ptr->hash_alg = sign_option.hash_alg; + key_ptr->sig_alg = vb2_rsa_sig_alg(key_ptr->rsa_private_key); + if (key_ptr->sig_alg == VB2_SIG_INVALID) { + fprintf(stderr, "Unsupported sig algorithm in RSA key\n"); + goto done; + } + + /* Figure out what needs signing */ + sig_size = vb2_rsa_sig_size(key_ptr->sig_alg); + if (rw_size < sig_size) { + fprintf(stderr, + "The RW image is too small to hold the signature" + " (0x%08x < %08x)\n", rw_size, sig_size); + goto done; + } + rw_size -= sig_size; + sig_offset = rw_offset + rw_size; + + Debug("rw_size => 0x%08x\n", rw_size); + Debug("rw_offset => 0x%08x\n", rw_offset); + Debug("sig_size 0x%08x\n", sig_size); + Debug("sig_offset 0x%08x\n", sig_offset); + + /* Sign the blob */ + r = vb2_sign_data(&sig_ptr, buf + rw_offset, rw_size, key_ptr, "Bah"); + if (r) { + fprintf(stderr, + "Unable to sign data (error 0x%08x, if that helps)\n", + r); + goto done; + } + + /* Double-check the size */ + if (sig_ptr->sig_size != sig_size) { + fprintf(stderr, + "ERROR: sig size is %d bytes, not %d as expected.\n", + sig_ptr->sig_size, sig_size); + goto done; + } + + /* Okay, looking good. Update the signature. */ + memcpy(buf + sig_offset, + (uint8_t *)sig_ptr + sig_ptr->sig_offset, + sig_ptr->sig_size); + + + /* If there's no RO section, we're done. */ + if (!ro_size) { + retval = 0; + goto done; + } + + /* Otherwise, now update the public key */ + if (vb_keyb_from_rsa(key_ptr->rsa_private_key, + &keyb_data, &keyb_size)) { + fprintf(stderr, "Couldn't extract the public key\n"); + goto done; + } + Debug("keyb_size is 0x%x (%d):\n", keyb_size, keyb_size); + + /* + * Of course the packed public key format is different. Why would you + * think otherwise? Since the dawn of time, vboot has used this: + * + * uint32_t nwords size of RSA key in 32-bit words + * uint32_t n0inv magic RSA n0inv + * uint32_t n[nwords] magic RSA modulus little endian array + * uint32_t rr[nwords] magic RSA R^2 little endian array + * + * But for no discernable reason, the usbpd1 format uses this: + * + * uint32_t n[nwords] magic RSA modulus little endian array + * uint32_t rr[nwords] magic RSA R^2 little endian array + * uint32_t n0inv magic RSA n0inv + * + * There's no nwords field, and n0inv is last insted of first. Sigh. + */ + pub_size = keyb_size - 4; + + /* align pubkey size to 16-byte boundary */ + uint32_t pub_pad = pub_size; + pub_size = (pub_size + 16) / 16 * 16; + pub_pad = pub_size - pub_pad; + + pub_offset = ro_offset + ro_size - pub_size; + + if (ro_size < pub_size) { + fprintf(stderr, + "The RO image is too small to hold the public key" + " (0x%08x < %08x)\n", ro_size, pub_size); + goto done; + } + + /* How many bytes in the arrays? */ + uint32_t nbytes = 4 * (*(uint32_t *)keyb_data); + /* Source offsets from keyb_data */ + uint32_t src_ofs_n0inv = 4; + uint32_t src_ofs_n = src_ofs_n0inv + 4; + uint32_t src_ofs_rr = src_ofs_n + nbytes; + /* Dest offsets from buf */ + uint32_t dst_ofs_n = pub_offset + 0; + uint32_t dst_ofs_rr = dst_ofs_n + nbytes; + uint32_t dst_ofs_n0inv = dst_ofs_rr + nbytes; + + Debug("len 0x%08x ro_size 0x%08x ro_offset 0x%08x\n", + len, ro_size, ro_offset); + Debug("pub_size 0x%08x pub_offset 0x%08x nbytes 0x%08x\n", + pub_size, pub_offset, nbytes); + Debug("pub_pad 0x%08x\n", pub_pad); + + /* Copy n[nwords] */ + memcpy(buf + dst_ofs_n, + keyb_data + src_ofs_n, + nbytes); + /* Copy rr[nwords] */ + memcpy(buf + dst_ofs_rr, + keyb_data + src_ofs_rr, + nbytes); + /* Copy n0inv */ + memcpy(buf + dst_ofs_n0inv, + keyb_data + src_ofs_n0inv, + 4); + /* Pad with 0xff */ + memset(buf + dst_ofs_n0inv + 4, 0xff, pub_pad); + + /* Finally */ + retval = 0; +done: + if (key_ptr) + vb2_private_key_free(key_ptr); + if (keyb_data) + free(keyb_data); + + return retval; +} diff --git a/futility/futility_options.h b/futility/futility_options.h index 3d416d5b..c8d0a8a6 100644 --- a/futility/futility_options.h +++ b/futility/futility_options.h @@ -13,6 +13,8 @@ #define VBOOT_REFERENCE_FUTILITY_OPTIONS_H_ #include <stdint.h> #include "vboot_common.h" +#include "file_type.h" +#include "2rsa.h" struct show_option_s { VbPublicKey *k; @@ -53,7 +55,13 @@ struct sign_option_s { uint32_t pem_algo; char *pem_external; enum futil_file_type type; + enum vb2_hash_algorithm hash_alg; + uint32_t ro_size, rw_size; + uint32_t ro_offset, rw_offset; }; extern struct sign_option_s sign_option; +/* Return true if hash_alg was identified, either by name or number */ +int vb2_lookup_hash_alg(const char *str, enum vb2_hash_algorithm *alg); + #endif /* VBOOT_REFERENCE_FUTILITY_OPTIONS_H_ */ diff --git a/futility/vb2_helper.c b/futility/vb2_helper.c index c10190ff..4ee0a28b 100644 --- a/futility/vb2_helper.c +++ b/futility/vb2_helper.c @@ -22,6 +22,33 @@ #include "file_type.h" #include "futility.h" +int vb2_lookup_hash_alg(const char *str, enum vb2_hash_algorithm *alg) +{ + const struct vb2_text_vs_enum *entry; + uint32_t val; + char *e; + + /* try string first */ + entry = vb2_lookup_by_name(vb2_text_vs_hash, str); + if (entry) { + *alg = entry->num; + return 1; + } + + /* fine, try number */ + val = strtoul(str, &e, 0); + if (!*str || (e && *e)) + /* that's not a number */ + return 0; + + if (!vb2_lookup_by_num(vb2_text_vs_hash, val)) + /* That's not a valid alg */ + return 0; + + *alg = val; + return 1; +} + enum futil_file_type ft_recognize_vb2_key(uint8_t *buf, uint32_t len) { struct vb2_public_key pubkey; diff --git a/tests/futility/data/dingdong.pem b/tests/futility/data/dingdong.pem new file mode 100644 index 00000000..e2ff6781 --- /dev/null +++ b/tests/futility/data/dingdong.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAqhcIe02T0+guB+QDIKTy578gwH0W0BpZM4B0scTq0ozQ6YJe +9O74HBWYlWUkbx+/AaM50yeroqx6DC4ZLgm8PcBFpCkxhuOdP6BZbjEqEoI4nVOg +nDsW3XpNODYueA7IpqiOjUgAcAeNTEfdxIGGh6XWwsJmGdbJCWu4SiWsKyJVThCr +1DPh3nPEmzDpX4CYU93qFeoJptKKH0DJcMKEP3CR8H0OU9S5wLoA10s9TECsWMN9 +z7vZQaelxsFrzHPgY2amX1uruSI4BaZ8aGYTtKzcTkzSnT/jD8QTiDnSYsMXs7h4 +6af24h3SZdApB5yFYQqcS80DWgHcubeT24ulXwIDAQABAoIBAAslnUmvaNu/YJzl +xYqzJLQpY3UZ/Y+/2k60wXERDa6kyeAzyhNVQe9dPvWzfjLGKtdpohWDiQ0NLqZz +svTAcJS/cBD1HijP6/NKh/HfyPkTjbBJ1cHHYZU8OalQa7U0itPZQhZiPJ0a8Zip +MRB6yJ1FMhDrepOA7wXuCFLbqy/cYcY+MdKL6Fny5FFIBMq16EeFOKBOR+DZsLEg +R71n1rV7IzxTIfcjD8ws43bRM0sbwykoaHUIYuwXO/AIII9QX75V7nQjB0JUOSYo +Z9OrrUaf+rP8l4Rd76tTHxrpMU3dy8C/ht5jpXbiMYViOl0pNDAzJfCvIx0+q9Iy +BrMLKUkCgYEA21jJ6Yqz9Nwkv/kcovYpiBuUHhMjmdsMv0LZnWWELCpXmisemeWJ +8FrnaMTTrYscbIn+MPkLQbb2FQHyT+HHtHchsps8i+snYEBBky0fyAlWG0LL/Rvh +GPFkKNXeMFRcGg7rTp51L0DhG6hbWgCkck3AtcHy86LgehsDaWhEi+0CgYEAxoMi +35F1Q0PMlpftK5sRYvwO5jSM2RvYxhqDImghyW43Bnc0tu7bVK25V+Vd3ZRBnjm5 +8E6A6UpP0By4qaEQuG1kMoZ2TTOix2q0AbltOGYuzLq41PirvINqj3DVzw3M4IZE +dL6PtiJcOGeFodL12Sz1QRZVksMfpxz0XaVpxPsCgYAmDDi58f1VM/qL8kItYlXB +7ka7EMbUIVMMuiPVUY6jupSHgYNFXrOWpa4OVlYBfGfpy+XzyL9THtGAw12szZU+ +kIuf152hB6FE6OB3DxS8NiJhiCyqMvPQx85/5tkruPZg7sWSVZouICrsCUAPVJ0x +1pre7E2gRVh61cS5vARn4QKBgQCNxp6jeal8LvHxI/R5Tjiur0Kc2y806BR79/ds +HV70E8kszvpRJGp1IdXblq7hT79FmAjaPdcHxtEV201vqN7eORJ0m1/mZ1h8gBKr +oJkGzMPj5/+V6zwMWPdEFtw9EqgeOwatMmRFOmkOx7DDEH4Ra3CF2cOoG7+BhMZq +E3dk/QKBgQCYXqptB56sUrjnCXKEAdR96SDlVCmL7BBI893xDSAYIKhbpQsI2YY1 +dcFb02bnMbpqjkwHqpjHD8MJOWvXf8q/5FxDjHBSLSL8fM2PL9DI65c8MmwpHUSZ +ZdcRhMrlN1iTkzw7WdfFCqb0HNl73sP5baqbRZgC+gysmDtgTZxBTQ== +-----END RSA PRIVATE KEY----- diff --git a/tests/futility/data/dingdong.signed b/tests/futility/data/dingdong.signed Binary files differnew file mode 100644 index 00000000..4b2a18bf --- /dev/null +++ b/tests/futility/data/dingdong.signed diff --git a/tests/futility/data/dingdong.unsigned b/tests/futility/data/dingdong.unsigned Binary files differnew file mode 100644 index 00000000..4b18fbf5 --- /dev/null +++ b/tests/futility/data/dingdong.unsigned diff --git a/tests/futility/data/hoho.pem b/tests/futility/data/hoho.pem new file mode 100644 index 00000000..08d5bd41 --- /dev/null +++ b/tests/futility/data/hoho.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEApfbLqgOYIM6AfRI6SJcj1Crengsp+yjHXtwZFOH6WDVP5Q9c +KSbwqoKHEKTbWJ90ymjqjfi382hl64L/V6J8SfIqGhrFztwXLhJOwFXRK5Jgzkk+ +YUByDzAKTKOlzvvRqk10Tq5a3wphg1SxGVLLOOsTGoKhGI93Wkf2j8AibMlVVZzz +Q8DmVszkYZL+Kchv6h1FgSvBW0oZa5tVod+0XToWSrPEYnBWs0zZEywCusIXMy7D +LaqMPFB4LTkDZ9Ne8jnB5xRad+ME4CgxZqUwGC7tdFdHdiiXpIwzIoxVk6xFIZUF +uusG4RR3O2ubaPJ/Fpf3UuuCWmddk37WaC7o7QIDAQABAoIBAAG4L94AEYhte0lQ +cggkgLuHAi1zAilW/9HMx/m+aaCWVNCTuym1/JJXrdyPSLJ/XG9obN2xsP41m7C3 +97tJtK3zc1o34srE3vycNfKqMPOZnaUlfx700vmzTrgCjgo5868nBEh4Z/qdmesJ +aphPkklxrg39QnwFqH/n9PcCT5j+7LyCeWeGbWxKfpzP2CT6v8XxT3XY1mtFSa4j +dfYaqb+aunYAhjEb4gqa48hyNTQAZskDOUr1TK433wbGqRughXXrQQix+FBW483u +IGo8aGgiQsjYxHX+ynNTMKW1Oap9WZRWVxF09Ph1f3MT+k3gKqM/0AejlDfBuTDu +aLxiKIUCgYEA1FZmfGn4RNlghv/ZCAlfWqbf5NA1/wA/Knk8u0R+kMQ71e8NFjOc +Ym3Uix+89KcKDBIgHn1360pNvSCeTyVU28wQ2bst5s6pvu4FYDvjym2nTgXcFJX6 +DDnZfVZ+WLSFR8E76LQLJGd00DSq0/uBw3ULyRSirkuQnFI3w3u4BH8CgYEAyBdD +UMV83kwQaDMuGgKqZtD4Ou3s/MDzMwcNgUSjLIueFdsXVnlzYQwwJXuLFkrp5COx +Zyoha/d1QQawnYehKmHWWy7qN/l0CO+F2DGb1E6pNXJrn+zn33Mgz9ms8421eqqn +ATQbq6ZQInk1IrkLfyZ3t09l6cyBMJuJjkoBrJMCgYA2Hfsq1FtJONnILmbjDHh4 +AzXm/EX2wtpWeeXHmLJlNQ5G/REpymeeEn3sI1+mPvhpkSkMfE/W8O4VOL4AT/Rr +vHvC8ljFjYBnwAQwvbLVwdK1KPspZ/v9p7TNpAC5nPCnFBGvwktgsNltwy6SrnQp +G6iwTAkWQP4PSUkbEmoZAwKBgF0OLJlQ70y3FV5Qhx1DphohD4DgjDnURoaxvf8j +e7vIxuGlPgpSe21j7LRR65KXjoUycFvpRRfgQyDVyqfInxSF4doQTI9xrRxGwPmV +wMIRPzKDHziGRiQud9ESjBPNENyWpwqxQDkpJNWThzm503Xz3vNasqv0FxUTEPsi +wfqPAoGABXPl7baUkpYzppAJqRlGNxsMjpbWscDPjmPosrGs6d81DP287s/IjfDR +ysQptvhJRK/lubM8As+d0/VLd6P8wk8dyZR1nRELwnVaPC55cS5+YIjgXK9TBmLA +hC0BIgujJS2qbXQRQF7yX925Gg77WLN2sJqtVg1Brine056pHTA= +-----END RSA PRIVATE KEY----- diff --git a/tests/futility/data/hoho.signed b/tests/futility/data/hoho.signed Binary files differnew file mode 100644 index 00000000..6a6bc1ae --- /dev/null +++ b/tests/futility/data/hoho.signed diff --git a/tests/futility/data/hoho.unsigned b/tests/futility/data/hoho.unsigned Binary files differnew file mode 100644 index 00000000..6a605d12 --- /dev/null +++ b/tests/futility/data/hoho.unsigned diff --git a/tests/futility/data/minimuffin.pem b/tests/futility/data/minimuffin.pem new file mode 100644 index 00000000..6912b1f4 --- /dev/null +++ b/tests/futility/data/minimuffin.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEAvI3KBubudlZyX1oBNzWhQ+bNemHNVC5bO7TjJMTYTIJeKTaW +IyHCFLF9ztpe8tT9Y+ga4VO9PEktP1WJpdU0ecG6VwK3951/cElosfnIPmIY7dVp +PQtGtGS/Zih1nTMRV5hqtGa9SRg0i2kdph+quFXGQoMriTl0StmvNVtD51nRPGwc +ZsG9+P0yfnyo7l3qXtKu5gBx/jDne2kl5/isPHkKfl9le+aNQaNjWeJyB4XDqHXM +AjuW1G7FxoKlU4b363gQbE84Q80X1Qd9iAoRj/HLmDrx9h6FDFs+HbKDfCYtg2fK +upEHr1bFUCxjc6AWuFglSq0yn5kyp1Bh5CD3PQIDAQABAoIBAQCNO2NlEhrx9sSK +mX8pnHkjxECK97D16hcaPN6azvr5K/ldw25n+ERIfb4vb7AJEfKOn+9qce/ftSw4 +MVj+Jxm8TZjGzdmAlq87KzFJhkAwQghMNTszpzuZqZEX8xxN2E+YHilm4UHM+114 +Qw8bPMMCefUcIuY8ThXGbxFm1Oqi4YHHfqE6waRc0XXnLZOYr7NDCmhgyUG1dpAH +kW0EYuJ1UNGaKE4LsWKvi0SYBQ48Mqh1XPkyiL/5I2whewsU2K4KEjynZp0+ULUG +Dxfv3uCywsSsLuNR+EV5tTUp4eY1BLKULJQTMH3hyV1Xf1qEt2YN/3ZHsv7MPQzS +sPIdN+LhAoGBAN6wbcxPnfkJROOVRUzE05IEEBalVULLo1cA1ss/7RjIeUvdRCAa +12OxF4LSNzrSxcPCLsDnYq+j4HoS6KZ31c1TbaKcaUOPfRohrtGBZMxPgDTZgEBa +JlsVtD2vzYvfUIpVQFz6Tnix3F29Gq5RaZdW5/qwOYyx0wtUrPf+pwZ5AoGBANjC +MjgoGtcubR6chDhZcFU4vopdL7IEhMOZ1qxLFTQnINGXXDJpgVvdJRKdDV29DjNZ +zF9wgmoiVm+uM/344bquUV7KHl5bEsZ+4KH6EA4y3IKVgxaxU7dpF6Q6L+rAuYp/ +j0N9XoVnS3aq30HkTkt+jQe0Hl6eEDOJqHEjolXlAoGBAJbMqs3cbIGkQT5May1d +bFhI4Aw10dL1y5qzOsFQfOJ3f4xcPjHve0RLPDye1j/DU6EI8lg3WKDQPMbt3xY7 +uFDe2jNv7+iMVo9Hl/bPxM6GV69ySmNJqQetXu0XC/5YL1Y9/OP5rQIWj7/6uwKo +pvSRKW6dv5sDIINfx/H4RGshAoGBAMIs7Tn7S1gaoev7QEMOdCAT7jUbF3/8pkZn +SLUdqcgHiVHYquIKO7TknbJX+MJReygrOHcC3gFf81imkLLiQqyuPfyRSbUzFtW0 +kVzpG3rsuzdL4pvwjNNQFLqs2YIN1eipLtjBtWwCRcrvdYKcmDrvCj2tcEtIg7D3 +j2qTBni1AoGBAI58xPHxB0cNclhWiFHPNgk98GkwADWxfeTZduoyfpraSrpbseu8 +Cfgq1p5E2nM9jWx4jdKA/fxdD40bneupPi5w5SE2gmwtmQFR3TehI8gxNbEL2Gq6 +6ZkgxnGNxFaE6saHVDHKU8Q2bgzCI8JlOOtSjzKvbr+hsQMYHcEJxom6 +-----END RSA PRIVATE KEY----- diff --git a/tests/futility/data/minimuffin.signed b/tests/futility/data/minimuffin.signed Binary files differnew file mode 100644 index 00000000..7d60a743 --- /dev/null +++ b/tests/futility/data/minimuffin.signed diff --git a/tests/futility/data/minimuffin.unsigned b/tests/futility/data/minimuffin.unsigned Binary files differnew file mode 100644 index 00000000..e5c23018 --- /dev/null +++ b/tests/futility/data/minimuffin.unsigned diff --git a/tests/futility/data/zinger.pem b/tests/futility/data/zinger.pem new file mode 100644 index 00000000..6912b1f4 --- /dev/null +++ b/tests/futility/data/zinger.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEAvI3KBubudlZyX1oBNzWhQ+bNemHNVC5bO7TjJMTYTIJeKTaW +IyHCFLF9ztpe8tT9Y+ga4VO9PEktP1WJpdU0ecG6VwK3951/cElosfnIPmIY7dVp +PQtGtGS/Zih1nTMRV5hqtGa9SRg0i2kdph+quFXGQoMriTl0StmvNVtD51nRPGwc +ZsG9+P0yfnyo7l3qXtKu5gBx/jDne2kl5/isPHkKfl9le+aNQaNjWeJyB4XDqHXM +AjuW1G7FxoKlU4b363gQbE84Q80X1Qd9iAoRj/HLmDrx9h6FDFs+HbKDfCYtg2fK +upEHr1bFUCxjc6AWuFglSq0yn5kyp1Bh5CD3PQIDAQABAoIBAQCNO2NlEhrx9sSK +mX8pnHkjxECK97D16hcaPN6azvr5K/ldw25n+ERIfb4vb7AJEfKOn+9qce/ftSw4 +MVj+Jxm8TZjGzdmAlq87KzFJhkAwQghMNTszpzuZqZEX8xxN2E+YHilm4UHM+114 +Qw8bPMMCefUcIuY8ThXGbxFm1Oqi4YHHfqE6waRc0XXnLZOYr7NDCmhgyUG1dpAH +kW0EYuJ1UNGaKE4LsWKvi0SYBQ48Mqh1XPkyiL/5I2whewsU2K4KEjynZp0+ULUG +Dxfv3uCywsSsLuNR+EV5tTUp4eY1BLKULJQTMH3hyV1Xf1qEt2YN/3ZHsv7MPQzS +sPIdN+LhAoGBAN6wbcxPnfkJROOVRUzE05IEEBalVULLo1cA1ss/7RjIeUvdRCAa +12OxF4LSNzrSxcPCLsDnYq+j4HoS6KZ31c1TbaKcaUOPfRohrtGBZMxPgDTZgEBa +JlsVtD2vzYvfUIpVQFz6Tnix3F29Gq5RaZdW5/qwOYyx0wtUrPf+pwZ5AoGBANjC +MjgoGtcubR6chDhZcFU4vopdL7IEhMOZ1qxLFTQnINGXXDJpgVvdJRKdDV29DjNZ +zF9wgmoiVm+uM/344bquUV7KHl5bEsZ+4KH6EA4y3IKVgxaxU7dpF6Q6L+rAuYp/ +j0N9XoVnS3aq30HkTkt+jQe0Hl6eEDOJqHEjolXlAoGBAJbMqs3cbIGkQT5May1d +bFhI4Aw10dL1y5qzOsFQfOJ3f4xcPjHve0RLPDye1j/DU6EI8lg3WKDQPMbt3xY7 +uFDe2jNv7+iMVo9Hl/bPxM6GV69ySmNJqQetXu0XC/5YL1Y9/OP5rQIWj7/6uwKo +pvSRKW6dv5sDIINfx/H4RGshAoGBAMIs7Tn7S1gaoev7QEMOdCAT7jUbF3/8pkZn +SLUdqcgHiVHYquIKO7TknbJX+MJReygrOHcC3gFf81imkLLiQqyuPfyRSbUzFtW0 +kVzpG3rsuzdL4pvwjNNQFLqs2YIN1eipLtjBtWwCRcrvdYKcmDrvCj2tcEtIg7D3 +j2qTBni1AoGBAI58xPHxB0cNclhWiFHPNgk98GkwADWxfeTZduoyfpraSrpbseu8 +Cfgq1p5E2nM9jWx4jdKA/fxdD40bneupPi5w5SE2gmwtmQFR3TehI8gxNbEL2Gq6 +6ZkgxnGNxFaE6saHVDHKU8Q2bgzCI8JlOOtSjzKvbr+hsQMYHcEJxom6 +-----END RSA PRIVATE KEY----- diff --git a/tests/futility/data/zinger.signed b/tests/futility/data/zinger.signed Binary files differnew file mode 100644 index 00000000..72d98a88 --- /dev/null +++ b/tests/futility/data/zinger.signed diff --git a/tests/futility/data/zinger.unsigned b/tests/futility/data/zinger.unsigned Binary files differnew file mode 100644 index 00000000..f36c37d0 --- /dev/null +++ b/tests/futility/data/zinger.unsigned diff --git a/tests/futility/run_test_scripts.sh b/tests/futility/run_test_scripts.sh index e8bbd232..8e6281a1 100755 --- a/tests/futility/run_test_scripts.sh +++ b/tests/futility/run_test_scripts.sh @@ -51,6 +51,7 @@ ${SCRIPTDIR}/test_sign_firmware.sh ${SCRIPTDIR}/test_sign_fw_main.sh ${SCRIPTDIR}/test_sign_kernel.sh ${SCRIPTDIR}/test_sign_keyblocks.sh +${SCRIPTDIR}/test_sign_usbpd1.sh ${SCRIPTDIR}/test_file_types.sh " diff --git a/tests/futility/test_file_types.c b/tests/futility/test_file_types.c index a2d03bf7..3fb21cc6 100644 --- a/tests/futility/test_file_types.c +++ b/tests/futility/test_file_types.c @@ -37,6 +37,7 @@ static struct { {FILE_TYPE_VB2_PUBKEY, "tests/futility/data/sample.vbpubk2"}, {FILE_TYPE_VB2_PRIVKEY, "tests/futility/data/sample.vbprik2"}, {FILE_TYPE_PEM, "tests/testkeys/key_rsa2048.pem"}, + {FILE_TYPE_USBPD1, }, }; BUILD_ASSERT(ARRAY_SIZE(test_case) == NUM_FILE_TYPES); diff --git a/tests/futility/test_sign_usbpd1.sh b/tests/futility/test_sign_usbpd1.sh new file mode 100755 index 00000000..dc3b6420 --- /dev/null +++ b/tests/futility/test_sign_usbpd1.sh @@ -0,0 +1,56 @@ +#!/bin/bash -eux +# 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. + +me=${0##*/} +TMP="$me.tmp" + +# Work in scratch directory +cd "$OUTDIR" + +# The signed input images are signed with dev keys. We resign the unsigned +# images with the same keypair, to make sure that we're producing identical +# binaries. + +DATADIR="${SCRIPTDIR}/data" +TESTS="dingdong hoho minimuffin zinger" + +set -o pipefail + +count=0 +for test in $TESTS; do + + : $(( count++ )) + echo -n "$count " 1>&3 + + pemfile=${DATADIR}/${test}.pem + infile=${DATADIR}/${test}.unsigned + goodfile=${DATADIR}/${test}.signed + outfile=${TMP}.${test}.new + + # Signing the whole thing with futility should produce identical results + ${FUTILITY} sign --type usbpd1 --pem ${pemfile} ${infile} ${outfile} + cmp ${goodfile} ${outfile} + + # Now try signing just the RW part + size=$(stat -c '%s' ${infile}) + half=$(( size / 2 )) + + newin=${TMP}.${test}.rw_in + dd if=${infile} bs=${half} count=1 skip=1 of=${newin} + newgood=${TMP}.${test}.rw_ok + dd if=${goodfile} bs=${half} count=1 skip=1 of=${newgood} + newout=${TMP}.${test}.rw_out + + # Sign the RW part alone + ${FUTILITY} sign --type usbpd1 --pem ${pemfile} \ + --ro_size 0 \ + ${newin} ${newout} + cmp ${newgood} ${newout} + +done + +# cleanup +rm -rf ${TMP}* +exit 0 |