diff options
-rw-r--r-- | Makefile.rules | 23 | ||||
-rw-r--r-- | board/dingdong/board.h | 1 | ||||
-rw-r--r-- | board/hammer/board.h | 1 | ||||
-rw-r--r-- | board/hoho/board.h | 1 | ||||
-rw-r--r-- | board/honeybuns/board.h | 1 | ||||
-rw-r--r-- | board/lucid/board.h | 1 | ||||
-rw-r--r-- | board/zinger/board.h | 1 | ||||
-rw-r--r-- | common/firmware_image.S | 19 | ||||
-rw-r--r-- | common/firmware_image.lds.S | 13 | ||||
-rw-r--r-- | common/fmap.c | 27 | ||||
-rw-r--r-- | common/rwsig.c | 92 | ||||
-rw-r--r-- | include/2id.h | 32 | ||||
-rw-r--r-- | include/config.h | 9 | ||||
-rw-r--r-- | include/rsa.h | 32 | ||||
-rw-r--r-- | include/vb21_struct.h | 346 | ||||
-rw-r--r-- | test/rsa2048-3.h | 8 | ||||
-rw-r--r-- | test/rsa2048-F4.h | 8 | ||||
-rw-r--r-- | test/test_config.h | 2 |
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 |