summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2017-02-10 13:59:39 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-02-17 04:09:37 -0800
commit07eccbb414962c09d411e8afeb6cfca71aebf838 (patch)
treecfd29416f3fe0ca397f5606ebbe19773ffa59e94
parentcb6e3ec3a0db005e62c94e3d8b667d4ef4a2d8d9 (diff)
downloadchrome-ec-07eccbb414962c09d411e8afeb6cfca71aebf838.tar.gz
rwsig: Add support for rwsig image types
usbpd1 futility image type is deprecated and should not be used for new designs. This adds proper support for rwsig image type. Key and signatures are added at linker stage step (futility cannot directly create such signed images). Thanks to VB21 header, rwsig.c can now tell how many bytes of the RW image need to be cryptographically verified, and ensure that the rest is blank (0xff). BRANCH=none BUG=chromium:690773 TEST=make BOARD=hammer; flash, RW image is verified correctly. TEST=make runtests -j TEST=For the rest of the tests: Change config option to CONFIG_RWSIG_TYPE_RWSIG TEST=make BOARD=hammer; flash, hammer still verifies correctly. TEST=cp build/hammer/ec.RW.bin build/hammer/ec.RW.bin.orig; futility sign --type rwsig --prikey build/hammer/key.vbprik2 \ build/hammer/ec.RW.bin diff build/hammer/ec.RW.bin build/hammer/ec.RW.bin.orig => Same file TEST=Add CONFIG_CMD_FLASH, flashwrite 0x1e000, reboot, EC does not verify anymore. TEST=dump_fmap build/hammer/ec.bin shows KEY_RO and SIG_RW at correct locations. Change-Id: I50ec828284c2d1eca67fa8cbddaf6f3b06606c82 Reviewed-on: https://chromium-review.googlesource.com/441546 Commit-Ready: Nicolas Boichat <drinkcat@chromium.org> Tested-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--Makefile.rules23
-rw-r--r--board/dingdong/board.h1
-rw-r--r--board/hammer/board.h1
-rw-r--r--board/hoho/board.h1
-rw-r--r--board/honeybuns/board.h1
-rw-r--r--board/lucid/board.h1
-rw-r--r--board/zinger/board.h1
-rw-r--r--common/firmware_image.S19
-rw-r--r--common/firmware_image.lds.S13
-rw-r--r--common/fmap.c27
-rw-r--r--common/rwsig.c92
-rw-r--r--include/2id.h32
-rw-r--r--include/config.h9
-rw-r--r--include/rsa.h32
-rw-r--r--include/vb21_struct.h346
-rw-r--r--test/rsa2048-3.h8
-rw-r--r--test/rsa2048-F4.h8
-rw-r--r--test/test_config.h2
18 files changed, 590 insertions, 27 deletions
diff --git a/Makefile.rules b/Makefile.rules
index b9364d1b56..d8bfd68bc7 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -91,8 +91,18 @@ cmd_sharedlib_elf = $(CC) $(libsharedobjs_deps) \
-o $(out)/$(SHOBJLIB)/$(SHOBJLIB).elf \
-Wl,-Map,$(out)/$(SHOBJLIB)/$(SHOBJLIB).map
-# commands for RSA signature
-cmd_rsasign = futility sign --type usbpd1 --pem $(PEM) $(out)/$*.bin.tmp
+# commands for RSA signature: rwsig does not need to sign the whole image
+# (it signs the RW part separately). usbpd1 type needs to sign the final image.
+ifeq ($(CONFIG_RWSIG_TYPE_RWSIG),)
+ cmd_rsasign = futility sign --type usbpd1 --pem $(PEM) $(out)/$*.bin.tmp
+else
+ cmd_rsasign =
+endif
+
+cmd_key_extract = futility create $(PEM) $(out)/$* $(silent)
+
+cmd_rsasign_rwsig = futility sign --type rwsig \
+ --prikey $(out)/key.vbprik2 $< $@
# commands to build optional xref files
cmd_deps_to_list = cat $(deps) | tr -d ':\\' | tr ' ' '\012' \
@@ -274,6 +284,9 @@ flat-$(CONFIG_FW_INCLUDE_RO) += $(out)/RO/$(PROJECT).RO.flat
deps += $(out)/firmware_image.lds.d $(flat-y:%.flat=%.lds.d)
+flat-$(CONFIG_RWSIG_TYPE_RWSIG) += $(out)/key.vbpubk2
+flat-$(CONFIG_RWSIG_TYPE_RWSIG) += $(out)/RW/$(PROJECT).RW.flat.sig
+
flat-$(CONFIG_SHAREDLIB) += $(libsharedobjs-y)
$(out)/$(PROJECT).obj: common/firmware_image.S $(out)/firmware_image.lds \
@@ -305,6 +318,12 @@ endif
$(out)/$(PROJECT).hex: $(out)/$(PROJECT).bin
$(call quiet,bin_to_hex,OBJCOPY)
+$(out)/%.vbprik2 $(out)/%.vbpubk2: $(PEM)
+ $(call quiet,key_extract,KEY )
+
+$(out)/RW/%.flat.sig: $(out)/RW/%.flat $(out)/key.vbprik2
+ $(call quiet,rsasign_rwsig,SIGN )
+
$(out)/RW/%.elf: override BLD:=RW
$(out)/RW/%.elf: private objs := $(rw-objs)
$(out)/RW/%.elf: $(out)/RW/%.lds $(rw-objs) $(libsharedobjs_elf-y)
diff --git a/board/dingdong/board.h b/board/dingdong/board.h
index 4c33b4ba45..5f22ef5b08 100644
--- a/board/dingdong/board.h
+++ b/board/dingdong/board.h
@@ -21,6 +21,7 @@
#define CONFIG_HW_CRC
#define CONFIG_RSA
#define CONFIG_RWSIG
+#define CONFIG_RWSIG_TYPE_USBPD1
#define CONFIG_SHA256
#define CONFIG_USB
#define CONFIG_USB_BOS
diff --git a/board/hammer/board.h b/board/hammer/board.h
index bc613ec920..a9c60a0807 100644
--- a/board/hammer/board.h
+++ b/board/hammer/board.h
@@ -78,6 +78,7 @@
/* Sign and switch to RW partition on boot. */
#define CONFIG_RWSIG
+#define CONFIG_RWSIG_TYPE_USBPD1
#define CONFIG_RSA
#define CONFIG_SHA256
#define CONFIG_RSA_KEY_SIZE 2048
diff --git a/board/hoho/board.h b/board/hoho/board.h
index d0c72f18b9..79f769ae0e 100644
--- a/board/hoho/board.h
+++ b/board/hoho/board.h
@@ -22,6 +22,7 @@
#define CONFIG_HW_CRC
#define CONFIG_RSA
#define CONFIG_RWSIG
+#define CONFIG_RWSIG_TYPE_USBPD1
#define CONFIG_SHA256
/* TODO(tbroch) Re-enable once STM spi master can be inhibited at boot so it
doesn't interfere with HDMI loading its f/w */
diff --git a/board/honeybuns/board.h b/board/honeybuns/board.h
index ad60fdb680..9cb147f87a 100644
--- a/board/honeybuns/board.h
+++ b/board/honeybuns/board.h
@@ -23,6 +23,7 @@
#undef CONFIG_LID_SWITCH
#define CONFIG_RSA
#define CONFIG_RWSIG
+#define CONFIG_RWSIG_TYPE_USBPD1
#define CONFIG_SHA256
#define CONFIG_STM_HWTIMER32
#undef CONFIG_TASK_PROFILING
diff --git a/board/lucid/board.h b/board/lucid/board.h
index cfae5c3bf3..0a7b759dfb 100644
--- a/board/lucid/board.h
+++ b/board/lucid/board.h
@@ -53,6 +53,7 @@
#define CONFIG_LTO
#define CONFIG_RSA
#define CONFIG_RWSIG
+#define CONFIG_RWSIG_TYPE_USBPD1
#define CONFIG_SHA256
#define CONFIG_STM_HWTIMER32
#define CONFIG_STM32_CHARGER_DETECT
diff --git a/board/zinger/board.h b/board/zinger/board.h
index 9a2a40afe8..1b11447614 100644
--- a/board/zinger/board.h
+++ b/board/zinger/board.h
@@ -49,6 +49,7 @@
#undef CONFIG_LID_SWITCH
#define CONFIG_LTO
#define CONFIG_RSA
+#define CONFIG_RWSIG_TYPE_USBPD1
#define CONFIG_SHA256
#undef CONFIG_TASK_PROFILING
#define CONFIG_USB_POWER_DELIVERY
diff --git a/common/firmware_image.S b/common/firmware_image.S
index 1fa4f25f71..97a7123f49 100644
--- a/common/firmware_image.S
+++ b/common/firmware_image.S
@@ -8,12 +8,15 @@
#include "config.h"
-#define FW_FILE(builddir,proj,sect,suffix) \
- builddir##/##sect##/##proj##.##sect##suffix##.flat
+#define FW_FILE(builddir,proj,sect,suffix,ext) \
+ builddir##/##sect##/##proj##.##sect##suffix##.flat##ext
+
#define STRINGIFY0(name) #name
#define STRINGIFY(name) STRINGIFY0(name)
#define FW_IMAGE(sect,suffix) \
- STRINGIFY(FW_FILE(FINAL_OUTDIR,PROJECT,sect,suffix))
+ STRINGIFY(FW_FILE(FINAL_OUTDIR,PROJECT,sect,suffix,))
+#define FW_IMAGE_SIGN(sect,suffix) \
+ STRINGIFY(FW_FILE(FINAL_OUTDIR,PROJECT,sect,suffix,.sig))
/* Read Only firmware */
#ifdef CONFIG_FW_INCLUDE_RO
@@ -21,6 +24,11 @@
.incbin FW_IMAGE(RO,)
#endif
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+.section .image.RO.key, "a"
+.incbin STRINGIFY(FINAL_OUTDIR/key.vbpubk2)
+#endif
+
/* Shared objects library */
#ifdef CONFIG_SHAREDLIB
.section .image.libsharedobjs, "ax"
@@ -31,6 +39,11 @@
.section .image.RW, "ax"
.incbin FW_IMAGE(RW,)
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+.section .image.RW.sign, "a"
+.incbin FW_IMAGE_SIGN(RW,)
+#endif
+
#ifdef CONFIG_RW_B
.section .image.RW_B, "ax"
.incbin FW_IMAGE(RW,_B)
diff --git a/common/firmware_image.lds.S b/common/firmware_image.lds.S
index 1b846bd045..85d4a56aa1 100644
--- a/common/firmware_image.lds.S
+++ b/common/firmware_image.lds.S
@@ -4,6 +4,7 @@
*/
#include "config.h"
+#include "rsa.h"
OUTPUT_FORMAT(BFD_FORMAT, BFD_FORMAT, BFD_FORMAT)
OUTPUT_ARCH(BFD_ARCH)
@@ -25,6 +26,13 @@ SECTIONS
*(.image.RO)
} > FLASH =0xff
. = ALIGN(CONFIG_FLASH_BANK_SIZE);
+
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+ .image.RO.key : AT(CONFIG_RO_PUBKEY_ADDR) {
+ *(.image.RO.key)
+ } > FLASH =0xff
+#endif
+
#ifdef CONFIG_SHAREDLIB
.image.libsharedobjs : AT(CONFIG_PROGRAM_MEMORY_BASE + \
CONFIG_SHAREDLIB_MEM_OFF) {
@@ -48,6 +56,11 @@ and RW images at different Flash offset */
#endif
*(.image.RW)
} > FLASH =0xff
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+ .image.RW.sign : AT(CONFIG_RW_SIG_ADDR) {
+ *(.image.RW.sign)
+ } > FLASH =0xff
+#endif
#ifdef CONFIG_RW_B_MEM_OFF
.image.RW_B : AT(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_B_MEM_OFF) {
*(.image.RW_B)
diff --git a/common/fmap.c b/common/fmap.c
index 6f84c37b63..f46b29b68e 100644
--- a/common/fmap.c
+++ b/common/fmap.c
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "common.h"
+#include "rsa.h"
#include "util.h"
#include "version.h"
@@ -61,7 +62,11 @@ struct fmap_area_header {
uint16_t area_flags;
} __packed;
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+#define NUM_EC_FMAP_AREAS 9
+#else
#define NUM_EC_FMAP_AREAS 7
+#endif
const struct _ec_fmap {
struct fmap_header header;
@@ -136,6 +141,17 @@ const struct _ec_fmap {
.area_size = CONFIG_WP_STORAGE_SIZE,
.area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
},
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+ {
+ /* RO public key address, for RW verification */
+ .area_name = "KEY_RO",
+ .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
+ FMAP_REGION_START + CONFIG_RO_PUBKEY_ADDR -
+ CONFIG_PROGRAM_MEMORY_BASE,
+ .area_size = CONFIG_RO_PUBKEY_SIZE,
+ .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
+ },
+#endif
/* RW Firmware */
{
@@ -162,5 +178,16 @@ const struct _ec_fmap {
.area_size = sizeof(version_data.version),
.area_flags = FMAP_AREA_STATIC,
},
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+ {
+ /* RW image signature */
+ .area_name = "SIG_RW",
+ .area_offset = CONFIG_EC_PROTECTED_STORAGE_OFF -
+ FMAP_REGION_START + CONFIG_RW_SIG_ADDR -
+ CONFIG_PROGRAM_MEMORY_BASE,
+ .area_size = CONFIG_RW_SIG_SIZE,
+ .area_flags = FMAP_AREA_STATIC | FMAP_AREA_RO,
+ },
+#endif
}
};
diff --git a/common/rwsig.c b/common/rwsig.c
index ee1bd6c9fc..1ad3ed37f9 100644
--- a/common/rwsig.c
+++ b/common/rwsig.c
@@ -15,6 +15,7 @@
#include "system.h"
#include "usb_pd.h"
#include "util.h"
+#include "vb21_struct.h"
/* Console output macros */
#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
@@ -24,12 +25,44 @@
static uint32_t * const rw_rst =
(uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF + 4);
+/*
+ * Check that memory between rwdata[start] and rwdata[len-1] is filled
+ * with ones. data, start and len must be aligned on 4-byte boundary.
+ */
+static int check_padding(const uint8_t *data,
+ unsigned int start, unsigned int len)
+{
+ unsigned int i;
+ const uint32_t *data32 = (const uint32_t *)data;
+
+ if ((start % 4) != 0 || (len % 4) != 0)
+ return 0;
+
+ for (i = start/4; i < len/4; i++) {
+ if (data32[i] != 0xffffffff)
+ return 0;
+ }
+
+ return 1;
+}
+
void check_rw_signature(void)
{
struct sha256_ctx ctx;
- int good, res;
+ int res;
+ const struct rsa_public_key *key;
+ const uint8_t *sig;
uint8_t *hash;
uint32_t *rsa_workbuf;
+ const uint8_t *rwdata = (uint8_t *)CONFIG_PROGRAM_MEMORY_BASE
+ + CONFIG_RW_MEM_OFF;
+ int good = 0;
+
+ unsigned int rwlen;
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+ const struct vb21_packed_key *vb21_key;
+ const struct vb21_signature *vb21_sig;
+#endif
/* Only the Read-Only firmware needs to do the signature check */
if (system_get_image_copy() != SYSTEM_IMAGE_RO)
@@ -48,17 +81,60 @@ void check_rw_signature(void)
return;
}
+#ifdef CONFIG_RWSIG_TYPE_USBPD1
+ key = (const struct rsa_public_key *)CONFIG_RO_PUBKEY_ADDR;
+ sig = (const uint8_t *)CONFIG_RW_SIG_ADDR;
+ rwlen = CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE;
+#elif defined(CONFIG_RWSIG_TYPE_RWSIG)
+ vb21_key = (const struct vb21_packed_key *)CONFIG_RO_PUBKEY_ADDR;
+ vb21_sig = (const struct vb21_signature *)CONFIG_RW_SIG_ADDR;
+
+ if (vb21_key->c.magic != VB21_MAGIC_PACKED_KEY ||
+ vb21_key->key_size != sizeof(struct rsa_public_key)) {
+ CPRINTS("Invalid key.");
+ goto out;
+ }
+
+ key = (const struct rsa_public_key *)
+ ((const uint8_t *)vb21_key + vb21_key->key_offset);
+
+ /*
+ * TODO(crbug.com/690773): We could verify other parameters such
+ * as sig_alg/hash_alg actually matches what we build for.
+ */
+ if (vb21_sig->c.magic != VB21_MAGIC_SIGNATURE ||
+ vb21_sig->sig_size != RSANUMBYTES ||
+ vb21_key->sig_alg != vb21_sig->sig_alg ||
+ vb21_key->hash_alg != vb21_sig->hash_alg ||
+ /* Sanity check signature offset and data size. */
+ vb21_sig->sig_offset < sizeof(vb21_sig) ||
+ (vb21_sig->sig_offset + RSANUMBYTES) > CONFIG_RW_SIG_SIZE ||
+ vb21_sig->data_size > (CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE)) {
+ CPRINTS("Invalid signature.");
+ goto out;
+ }
+
+ sig = (const uint8_t *)vb21_sig + vb21_sig->sig_offset;
+ rwlen = vb21_sig->data_size;
+#endif
+
+ /*
+ * Check that unverified RW region is actually filled with ones.
+ */
+ good = check_padding(rwdata, rwlen,
+ CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE);
+ if (!good) {
+ CPRINTS("Invalid padding.");
+ goto out;
+ }
+
/* SHA-256 Hash of the RW firmware */
- /* TODO(crosbug.com/p/44803): Do we have to hash the whole region? */
SHA256_init(&ctx);
- SHA256_update(&ctx, (void *)CONFIG_PROGRAM_MEMORY_BASE
- + CONFIG_RW_MEM_OFF,
- CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE);
+ SHA256_update(&ctx, rwdata, rwlen);
hash = SHA256_final(&ctx);
- good = rsa_verify((const struct rsa_public_key *)CONFIG_RO_PUBKEY_ADDR,
- (const uint8_t *)CONFIG_RW_SIG_ADDR,
- hash, rsa_workbuf);
+ good = rsa_verify(key, sig, hash, rsa_workbuf);
+out:
if (good) {
CPRINTS("RW image verified");
/* Jump to the RW firmware */
diff --git a/include/2id.h b/include/2id.h
new file mode 100644
index 0000000000..8daa4d27db
--- /dev/null
+++ b/include/2id.h
@@ -0,0 +1,32 @@
+/* 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.
+ *
+ * Key ID, used to quickly match keys with signatures. There's not a standard
+ * fingerprint for private keys, so we're using the sha1sum of the public key
+ * in our keyb format. Pretty much anything would work as long as it's
+ * resistant to collisions and easy to compare.
+ *
+ * Note: This file is copied from
+ * src/platform/vboot_reference/firmware/2lib/include/2id.h
+ * and should be updated if necessary.
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2ID_H_
+#define VBOOT_REFERENCE_VBOOT_2ID_H_
+#include <stdint.h>
+
+#define VB2_ID_NUM_BYTES 20
+
+struct vb2_id {
+ uint8_t raw[VB2_ID_NUM_BYTES];
+} __attribute__((packed));
+
+#define EXPECTED_ID_SIZE VB2_ID_NUM_BYTES
+
+/* IDs to use for "keys" with sig_alg==VB2_SIG_NONE */
+#define VB2_ID_NONE_SHA1 {{0x00, 0x01,}}
+#define VB2_ID_NONE_SHA256 {{0x02, 0x56,}}
+#define VB2_ID_NONE_SHA512 {{0x05, 0x12,}}
+
+#endif /* VBOOT_REFERENCE_VBOOT_2ID_H_ */
diff --git a/include/config.h b/include/config.h
index 3b2e6f3906..ef65989c6b 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1755,6 +1755,15 @@
* (for accessories without software sync)
*/
#undef CONFIG_RWSIG
+
+/*
+ * Defines what type of futility signature type should be used.
+ * RWSIG should be used for new designs.
+ * Old adapters use the USBPD1 futility signature type.
+ */
+#undef CONFIG_RWSIG_TYPE_RWSIG
+#undef CONFIG_RWSIG_TYPE_USBPD1
+
/*
* By default the pubkey and sig are put at the end of the first and second
* half of the total flash, and take up the minimum space possible. You can
diff --git a/include/rsa.h b/include/rsa.h
index 2fb896c652..ca3b227aae 100644
--- a/include/rsa.h
+++ b/include/rsa.h
@@ -22,6 +22,8 @@
* plus 4 for n0inv, aligned on a multiple of 16
* Put numerical constants here to please the linker script.
*/
+#ifndef CONFIG_RWSIG_TYPE_RWSIG
+/* vboot2 public keys are packed in a slightly different way. */
#if CONFIG_RSA_KEY_SIZE == 2048
#define RSA_PUBLIC_KEY_SIZE 528
#elif CONFIG_RSA_KEY_SIZE == 4096
@@ -31,18 +33,29 @@
#else
#error Unsupported RSA key size
#endif
+#endif /* ! CONFIG_RWSIG_TYPE_RWSIG */
#endif /* CONFIG_RSA */
#ifndef __ASSEMBLER__
#include "common.h"
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+/* RSA public key definition, VBoot2 packing */
+struct rsa_public_key {
+ uint32_t size;
+ uint32_t n0inv; /* -1 / n[0] mod 2^32 */
+ uint32_t n[RSANUMWORDS]; /* modulus as little endian array */
+ uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */
+};
+#else
/* RSA public key definition */
struct rsa_public_key {
uint32_t n[RSANUMWORDS]; /* modulus as little endian array */
uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */
uint32_t n0inv; /* -1 / n[0] mod 2^32 */
};
+#endif
int rsa_verify(const struct rsa_public_key *key,
const uint8_t *signature,
@@ -63,8 +76,19 @@ void check_rw_signature(void);
/* The pubkey goes at the end of the first half of flash */
#ifndef CONFIG_RO_PUBKEY_SIZE
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+/*
+ * rwsig type: 1024 bytes is enough to fit RSA-3072 public key.
+ *
+ * TODO(crosbug.com/p/62321): This still wastes space. We could pack the key at
+ * any arbitrary location, but we need proper signer support to make sure it
+ * can overwrite the key correctly.
+ */
+#define CONFIG_RO_PUBKEY_SIZE 1024
+#else
#define CONFIG_RO_PUBKEY_SIZE RSA_PUBLIC_KEY_SIZE
#endif
+#endif /* ! CONFIG_RO_PUBKEY_SIZE */
#ifndef CONFIG_RO_PUBKEY_ADDR
#define CONFIG_RO_PUBKEY_ADDR (CONFIG_PROGRAM_MEMORY_BASE \
+ (CONFIG_FLASH_SIZE / 2) \
@@ -73,8 +97,16 @@ void check_rw_signature(void);
/* The signature goes at the end of the second half of flash */
#ifndef CONFIG_RW_SIG_SIZE
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+/*
+ * rwsig type: futility expects signature to be 1024 bytes from the end of
+ * the file.
+ */
+#define CONFIG_RW_SIG_SIZE 1024
+#else
#define CONFIG_RW_SIG_SIZE RSANUMBYTES
#endif
+#endif /* ! CONFIG_RW_SIG_SIZE */
#ifndef CONFIG_RW_SIG_ADDR
#define CONFIG_RW_SIG_ADDR (CONFIG_PROGRAM_MEMORY_BASE \
+ CONFIG_FLASH_SIZE \
diff --git a/include/vb21_struct.h b/include/vb21_struct.h
new file mode 100644
index 0000000000..30adf84d04
--- /dev/null
+++ b/include/vb21_struct.h
@@ -0,0 +1,346 @@
+/* Copyright (c) 2014 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.
+ *
+ * Vboot 2.1 data structures
+ *
+ * Offsets should be padded to 32-bit boundaries, since some architectures
+ * have trouble with accessing unaligned integers.
+ *
+ * Note: This file is copied from
+ * src/platform/vboot_reference/firmware/lib21/include/vb21_struct.h
+ * and should be updated if necessary.
+ */
+
+#ifndef VBOOT_REFERENCE_VB21_STRUCT_H_
+#define VBOOT_REFERENCE_VB21_STRUCT_H_
+#include <stdint.h>
+
+#include "2id.h"
+
+/*
+ * Magic numbers used by vb21_struct_common.magic.
+ *
+ * All valid numbers should be listed here to avoid accidental overlap.
+ * Numbers start at a large value, so that previous parsers (which stored
+ * things like lengths and offsets at that field) will detect and reject new
+ * structs as invalid.
+ */
+enum vb21_struct_common_magic {
+ /* "Vb2B" = vb21_keyblock.c.magic */
+ VB21_MAGIC_KEYBLOCK = 0x42326256,
+
+ /* "Vb2F" = vb21_fw_preamble.c.magic */
+ VB21_MAGIC_FW_PREAMBLE = 0x46326256,
+
+ /* "Vb2I" = vb21_packed_private_key.c.magic */
+ VB21_MAGIC_PACKED_PRIVATE_KEY = 0x49326256,
+
+ /* "Vb2K" = vb2_kernel_preamble.c.magic */
+ VB21_MAGIC_KERNEL_PREAMBLE = 0x4b326256,
+
+ /* "Vb2P" = vb21_packed_key.c.magic */
+ VB21_MAGIC_PACKED_KEY = 0x50326256,
+
+ /* "Vb2S" = vb21_signature.c.magic */
+ VB21_MAGIC_SIGNATURE = 0x53326256,
+};
+
+
+/*
+ * Generic struct header for all vboot2.1 structs. This makes it easy to
+ * automatically parse and identify vboot structs (e.g., in futility). This
+ * must be the first member of the parent vboot2.1 struct.
+ */
+struct vb21_struct_common {
+ /* Magic number; see vb21_struct_common_magic for expected values */
+ uint32_t magic;
+
+ /*
+ * Parent struct version; see each struct for the expected value.
+ *
+ * How to handle struct version mismatches, if the parser is version
+ * A.b and the data is version C.d:
+ * 1) If A.b == C.d, we're good.
+ * 2) If A != C, the data cannot be parsed at all.
+ * 3) If b < d, C.d is a newer version of data which is backwards-
+ * compatible to old parsers. We're good.
+ * 4) If b > d, C.d is an older version of data. The parser should
+ * use default values for fields added after version d. We're
+ * good.
+ *
+ * Struct versions start at 3.0, since the highest version of the old
+ * structures was 2.1. This way, there is no possibility of collision
+ * for old code which depends on the version number.
+ */
+ uint16_t struct_version_major;
+ uint16_t struct_version_minor;
+
+ /*
+ * Size of the parent structure and all its data, including the
+ * description and any necessary padding. That is, all data must lie
+ * in a contiguous region of <total_size> bytes starting at the first
+ * byte of this header.
+ */
+ uint32_t total_size;
+
+ /*
+ * Size of the fixed portion of the parent structure. If a description
+ * is present, it must start at this offset.
+ */
+ uint32_t fixed_size;
+
+ /*
+ * The object may contain an ASCII description following the fixed
+ * portion of the structure. If it is present, it must be
+ * null-terminated, and padded with 0 (null) bytes to a multiple of 32
+ * bits.
+ *
+ * Size of ASCII description in bytes, counting null terminator and
+ * padding (if any). Set 0 if no description is present. If non-zero,
+ * there must be a null terminator (0) at offset (fixed_size +
+ * desc_size - 1).
+ */
+ uint32_t desc_size;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_STRUCT_COMMON_SIZE 20
+
+/* Current version of vb21_packed_key struct */
+#define VB21_PACKED_KEY_VERSION_MAJOR 3
+#define VB21_PACKED_KEY_VERSION_MINOR 0
+
+/*
+ * Packed public key data
+ *
+ * The key data must be arranged like this:
+ * 1) vb21_packed_key header struct h
+ * 2) Key description (pointed to by h.c.fixed_size)
+ * 3) Key data key (pointed to by h.key_offset)
+ */
+struct vb21_packed_key {
+ /* Common header fields */
+ struct vb21_struct_common c;
+
+ /* Offset of key data from start of this struct */
+ uint32_t key_offset;
+
+ /* Size of key data in bytes (NOT strength of key in bits) */
+ uint32_t key_size;
+
+ /* Signature algorithm used by the key (enum vb2_signature_algorithm) */
+ uint16_t sig_alg;
+
+ /*
+ * Hash digest algorithm used with the key (enum vb2_hash_algorithm).
+ * This is explicitly specified as part of the key to prevent use of a
+ * strong key with a weak hash.
+ */
+ uint16_t hash_alg;
+
+ /* Key version */
+ uint32_t key_version;
+
+ /* Key ID */
+ struct vb2_id id;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_PACKED_KEY_SIZE \
+ (EXPECTED_VB21_STRUCT_COMMON_SIZE + 16 + EXPECTED_ID_SIZE)
+
+/* Current version of vb21_packed_private_key struct */
+#define VB21_PACKED_PRIVATE_KEY_VERSION_MAJOR 3
+#define VB21_PACKED_PRIVATE_KEY_VERSION_MINOR 0
+
+/*
+ * Packed private key data
+ *
+ * The key data must be arranged like this:
+ * 1) vb21_packed_private_key header struct h
+ * 2) Key description (pointed to by h.c.fixed_size)
+ * 3) Key data key (pointed to by h.key_offset)
+ */
+struct vb21_packed_private_key {
+ /* Common header fields */
+ struct vb21_struct_common c;
+
+ /* Offset of key data from start of this struct */
+ uint32_t key_offset;
+
+ /* Size of key data in bytes (NOT strength of key in bits) */
+ uint32_t key_size;
+
+ /* Signature algorithm used by the key (enum vb2_signature_algorithm) */
+ uint16_t sig_alg;
+
+ /*
+ * Hash digest algorithm used with the key (enum vb2_hash_algorithm).
+ * This is explicitly specified as part of the key to prevent use of a
+ * strong key with a weak hash.
+ */
+ uint16_t hash_alg;
+
+ /* Key ID */
+ struct vb2_id id;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_PACKED_PRIVATE_KEY_SIZE \
+ (EXPECTED_VB21_STRUCT_COMMON_SIZE + 12 + EXPECTED_ID_SIZE)
+
+/* Current version of vb21_signature struct */
+#define VB21_SIGNATURE_VERSION_MAJOR 3
+#define VB21_SIGNATURE_VERSION_MINOR 0
+
+/*
+ * Signature data
+ *
+ * The signature data must be arranged like this:
+ * 1) vb21_signature header struct h
+ * 2) Signature description (pointed to by h.c.fixed_size)
+ * 3) Signature data (pointed to by h.sig_offset)
+ */
+struct vb21_signature {
+ /* Common header fields */
+ struct vb21_struct_common c;
+
+ /* Offset of signature data from start of this struct */
+ uint32_t sig_offset;
+
+ /* Size of signature data in bytes */
+ uint32_t sig_size;
+
+ /* Size of the data block which was signed in bytes */
+ uint32_t data_size;
+
+ /* Signature algorithm used (enum vb2_signature_algorithm) */
+ uint16_t sig_alg;
+
+ /* Hash digest algorithm used (enum vb2_hash_algorithm) */
+ uint16_t hash_alg;
+
+ /*
+ * ID for the signature.
+ *
+ * If this is a keyblock signature entry, this is the ID of the key
+ * used to generate this signature. This allows the firmware to
+ * quickly determine which signature block (if any) goes with the key
+ * being used by the firmware.
+ *
+ * If this is a preamble hash entry, this is the ID of the data type
+ * being hashed. There is no key ID, because sig_alg=VB2_ALG_NONE.
+ */
+ struct vb2_id id;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_SIGNATURE_SIZE \
+ (EXPECTED_VB21_STRUCT_COMMON_SIZE + 16 + EXPECTED_ID_SIZE)
+
+
+/* Current version of vb21_keyblock struct */
+#define VB21_KEYBLOCK_VERSION_MAJOR 3
+#define VB21_KEYBLOCK_VERSION_MINOR 0
+
+/*
+ * Key block. This contains a signed, versioned key for use in the next stage
+ * of verified boot.
+ *
+ * The key block data must be arranged like this:
+ * 1) vb21_keyblock header struct h
+ * 2) Keyblock description (pointed to by h.c.fixed_size)
+ * 3) Data key (pointed to by h.data_key_offset)
+ * 4) Signatures (first signature pointed to by h.sig_offset)
+ *
+ * The signatures from 4) must cover all the data from 1), 2), 3). That is,
+ * signatures must sign all data up to sig_offset.
+ */
+struct vb21_keyblock {
+ /* Common header fields */
+ struct vb21_struct_common c;
+
+ /* Flags (VB2_KEY_BLOCK_FLAG_*) */
+ uint32_t flags;
+
+ /*
+ * Offset of key (struct vb21_packed_key) to use in next stage of
+ * verification, from start of the keyblock.
+ */
+ uint32_t key_offset;
+
+ /* Number of keyblock signatures which follow */
+ uint32_t sig_count;
+
+ /*
+ * Offset of the first signature (struct vb21_signature) from the start
+ * of the keyblock.
+ *
+ * Signatures sign the contents of this struct and the data pointed to
+ * by data_key_offset, but not themselves or other signatures.
+ *
+ * For the firmware, there may be only one signature.
+ *
+ * Kernels often have at least two signatures - one using the kernel
+ * subkey from the RW firmware (for signed kernels) and one which is
+ * simply a SHA-512 hash (for unsigned developer kernels).
+ *
+ * The ID for each signature indicates which key was used to generate
+ * the signature.
+ */
+ uint32_t sig_offset;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_KEYBLOCK_SIZE (EXPECTED_VB21_STRUCT_COMMON_SIZE + 16)
+
+
+/* Current version of vb21_fw_preamble struct */
+#define VB21_FW_PREAMBLE_VERSION_MAJOR 3
+#define VB21_FW_PREAMBLE_VERSION_MINOR 0
+
+/* Flags for vb21_fw_preamble.flags */
+/* Reserved; do not use */
+#define VB21_FIRMWARE_PREAMBLE_RESERVED0 0x00000001
+/* Do not allow use of any hardware crypto accelerators. */
+#define VB21_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO 0x00000002
+
+/*
+ * Firmware preamble
+ *
+ * The preamble data must be arranged like this:
+ * 1) vb21_fw_preamble header struct h
+ * 2) Preamble description (pointed to by h.c.fixed_size)
+ * 3) Hashes (pointed to by h.hash_offset)
+ * 4) Signature (pointed to by h.sig_offset)
+ *
+ * The signature 4) must cover all the data from 1), 2), 3).
+ */
+struct vb21_fw_preamble {
+ /* Common header fields */
+ struct vb21_struct_common c;
+
+ /* Flags; see VB21_FIRMWARE_PREAMBLE_* */
+ uint32_t flags;
+
+ /* Firmware version */
+ uint32_t fw_version;
+
+ /* Offset of signature (struct vb21_signature) for this preamble */
+ uint32_t sig_offset;
+
+ /*
+ * The preamble contains a list of hashes (struct vb21_signature) for
+ * the various firmware components. These have sig_alg=VB2_SIG_NONE,
+ * and the ID for each hash identifies the component being hashed.
+ * The calling firmware is responsible for knowing where to find those
+ * components, which may be on a different storage device than this
+ * preamble.
+ */
+
+ /* Number of hash entries */
+ uint32_t hash_count;
+
+ /* Offset of first hash entry from start of preamble */
+ uint32_t hash_offset;
+} __attribute__((packed));
+
+#define EXPECTED_VB21_FW_PREAMBLE_SIZE (EXPECTED_VB21_STRUCT_COMMON_SIZE + 20)
+
+#endif /* VBOOT_REFERENCE_VB21_STRUCT_H_ */
diff --git a/test/rsa2048-3.h b/test/rsa2048-3.h
index 37119ffb70..d1b15c15a4 100644
--- a/test/rsa2048-3.h
+++ b/test/rsa2048-3.h
@@ -11,13 +11,9 @@
* # openssl rsa -in key.pem -pubout > key.pub
* Then dump the key:
* # dumpRSAPublicKey -pub key.pub | xxd -i
- * That's a slightly different format, so comment out the 1st 4 bytes (length),
- * and move the next 4 to the end (n0inv).
*/
const uint8_t rsa_data[] = {
- /* Length */
- /* 0x40, 0x00, 0x00, 0x00, */
- 0x11, 0x17, 0x38, 0xfd,
+ 0x40, 0x00, 0x00, 0x00, 0x0f, 0x46, 0xe8, 0x2c, 0x11, 0x17, 0x38, 0xfd,
0xef, 0xa2, 0xb5, 0x2d, 0x6d, 0x76, 0xe1, 0x70, 0x7d, 0x67, 0xb1, 0x9a,
0x18, 0x78, 0x90, 0xe2, 0xce, 0xa6, 0x81, 0xa0, 0x13, 0x37, 0xf2, 0x71,
0xf0, 0x44, 0x96, 0xaf, 0x52, 0x53, 0xd4, 0x23, 0x51, 0x19, 0xe5, 0xb0,
@@ -61,8 +57,6 @@ const uint8_t rsa_data[] = {
0x23, 0xa1, 0x21, 0x4e, 0x1f, 0x6e, 0xdd, 0xac, 0xa6, 0x2c, 0x83, 0x61,
0xdf, 0x8f, 0x9a, 0xfb, 0x55, 0x0a, 0x88, 0x0b, 0x0b, 0x34, 0xbd, 0x35,
0x43, 0x2d, 0xe4, 0x49,
- /* n0inv */
- 0x0f, 0x46, 0xe8, 0x2c
};
const struct rsa_public_key *rsa_key = (struct rsa_public_key *)rsa_data;
diff --git a/test/rsa2048-F4.h b/test/rsa2048-F4.h
index a145d756ac..afe66a198f 100644
--- a/test/rsa2048-F4.h
+++ b/test/rsa2048-F4.h
@@ -11,13 +11,9 @@
* # openssl rsa -in key.pem -pubout > key.pub
* Then dump the key:
* # dumpRSAPublicKey -pub key.pub | xxd -i
- * That's a slightly different format, so comment out the 1st 4 bytes (length),
- * and move the next 4 to the end (n0inv).
*/
const uint8_t rsa_data[] = {
- /* Length */
- /* 0x40, 0x00, 0x00, 0x00, */
- 0x3d, 0xbe, 0xa2, 0xde,
+ 0x40, 0x00, 0x00, 0x00, 0xeb, 0xb6, 0x8c, 0xb4, 0x3d, 0xbe, 0xa2, 0xde,
0x0c, 0xa8, 0x6b, 0xcc, 0x1b, 0x58, 0x2e, 0x1b, 0x44, 0x3f, 0xda, 0xdb,
0x1d, 0xe1, 0xe4, 0xfd, 0x4b, 0xc5, 0x34, 0xc9, 0x7e, 0x58, 0xfc, 0x82,
0x6d, 0x95, 0x9f, 0x46, 0x01, 0xaf, 0x7c, 0xa1, 0x50, 0xd5, 0x9c, 0x22,
@@ -61,8 +57,6 @@ const uint8_t rsa_data[] = {
0xcf, 0x5a, 0xa2, 0x66, 0x7a, 0xa2, 0x0e, 0x02, 0x56, 0x87, 0x98, 0x67,
0x90, 0xf4, 0x9f, 0x3b, 0xf7, 0xaa, 0x1c, 0xd9, 0xda, 0x0d, 0x49, 0x12,
0x50, 0xa3, 0x70, 0x62,
- /* n0inv */
- 0xeb, 0xb6, 0x8c, 0xb4
};
const struct rsa_public_key *rsa_key = (struct rsa_public_key *)rsa_data;
diff --git a/test/test_config.h b/test/test_config.h
index 5314dd5ebc..36bebe8a01 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -57,12 +57,14 @@
#ifdef TEST_RSA
#define CONFIG_RSA
#define CONFIG_RSA_KEY_SIZE 2048
+#define CONFIG_RWSIG_TYPE_RWSIG
#endif
#ifdef TEST_RSA3
#define CONFIG_RSA
#define CONFIG_RSA_KEY_SIZE 2048
#define CONFIG_RSA_EXPONENT_3
+#define CONFIG_RWSIG_TYPE_RWSIG
#endif
#ifdef TEST_SHMALLOC