diff options
-rw-r--r-- | firmware/include/vboot_struct.h | 10 | ||||
-rw-r--r-- | firmware/lib/include/vboot_common.h | 11 | ||||
-rw-r--r-- | firmware/lib/vboot_common.c | 19 | ||||
-rw-r--r-- | futility/cmd_show.c | 5 | ||||
-rw-r--r-- | futility/cmd_sign.c | 14 | ||||
-rw-r--r-- | futility/cmd_vbutil_kernel.c | 19 | ||||
-rw-r--r-- | futility/vb1_helper.c | 13 | ||||
-rw-r--r-- | futility/vb1_helper.h | 2 | ||||
-rw-r--r-- | host/lib/host_common.c | 2 | ||||
-rw-r--r-- | host/lib/include/host_common.h | 1 | ||||
-rw-r--r-- | host/linktest/main.c | 2 | ||||
-rw-r--r-- | tests/vboot_common2_tests.c | 2 | ||||
-rw-r--r-- | tests/vboot_common_tests.c | 2 |
13 files changed, 89 insertions, 13 deletions
diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h index 9e845ef8..09abf138 100644 --- a/firmware/include/vboot_struct.h +++ b/firmware/include/vboot_struct.h @@ -180,7 +180,7 @@ typedef struct VbFirmwarePreambleHeader { /****************************************************************************/ #define KERNEL_PREAMBLE_HEADER_VERSION_MAJOR 2 -#define KERNEL_PREAMBLE_HEADER_VERSION_MINOR 1 +#define KERNEL_PREAMBLE_HEADER_VERSION_MINOR 2 /* Preamble block for kernel, version 2.0 * @@ -260,9 +260,17 @@ typedef struct VbKernelPreambleHeader { /* Size of 16-bit header for vmlinuz in bytes. Readers should return 0 for header version < 2.1 */ uint64_t vmlinuz_header_size; + /* + * Flags passed in by the signer. Readers should return 0 for header + * version < 2.2. Flags field is currently defined as: + * [31:2] - Reserved (for future use) + * [1:0] - Kernel image type (0b00 - CrOS, 0b01 - bootimg) + */ + uint32_t flags; } __attribute__((packed)) VbKernelPreambleHeader; #define EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE 112 +#define EXPECTED_VBKERNELPREAMBLEHEADER2_2_SIZE 116 /****************************************************************************/ diff --git a/firmware/lib/include/vboot_common.h b/firmware/lib/include/vboot_common.h index f792d1a2..4d50ff62 100644 --- a/firmware/lib/include/vboot_common.h +++ b/firmware/lib/include/vboot_common.h @@ -41,6 +41,8 @@ enum { VBOOT_PREAMBLE_SIGNATURE, /* Shared data is invalid. */ VBOOT_SHARED_DATA_INVALID, + /* Kernel Preamble does not contain flags */ + VBOOT_KERNEL_PREAMBLE_NO_FLAGS, VBOOT_ERROR_MAX, }; extern const char *kVbootErrors[VBOOT_ERROR_MAX]; @@ -161,6 +163,15 @@ int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble, uint64_t *vmlinuz_header_size); /** + * Checks if the kernel preamble has flags field. This is available only if the + * Kernel Preamble Header version >=2.2. If give a header of 2.1 or lower, it + * will return VBOOT_KERNEL_PREAMBLE_NO_FLAGS. + * + * Returns VBOOT_SUCCESS if version is >=2.2. + */ +int VbKernelHasFlags(const VbKernelPreambleHeader *preamble); + +/** * Verify that the Vmlinuz Header is contained inside of the kernel blob. * * Returns VBOOT_SUCCESS or VBOOT_PREAMBLE_INVALID on error diff --git a/firmware/lib/vboot_common.c b/firmware/lib/vboot_common.c index 2cb01f37..226cdb7b 100644 --- a/firmware/lib/vboot_common.c +++ b/firmware/lib/vboot_common.c @@ -437,13 +437,20 @@ int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble, /* * If the preamble header version is at least 2.1, verify we have space - * for the added fields from 2.1. + * for the added fields from >2.1. */ if (preamble->header_version_minor >= 1) { - if(size < EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE) { + if((preamble->header_version_minor == 1) && + (size < EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE)) { VBDEBUG(("Not enough data for preamble header 2.1.\n")); return VBOOT_PREAMBLE_INVALID; } + + if((preamble->header_version_minor == 2) && + (size < EXPECTED_VBKERNELPREAMBLEHEADER2_2_SIZE)) { + VBDEBUG(("Not enough data for preamble header 2.2.\n")); + return VBOOT_PREAMBLE_INVALID; + } } /* Success */ @@ -469,6 +476,14 @@ int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble, return VBOOT_SUCCESS; } +int VbKernelHasFlags(const VbKernelPreambleHeader *preamble) +{ + if (preamble->header_version_minor > 1) + return VBOOT_SUCCESS; + + return VBOOT_KERNEL_PREAMBLE_NO_FLAGS; +} + int VerifyVmlinuzInsideKBlob(uint64_t kblob, uint64_t kblob_size, uint64_t header, uint64_t header_size) { diff --git a/futility/cmd_show.c b/futility/cmd_show.c index dc7c8141..b6c2574a 100644 --- a/futility/cmd_show.c +++ b/futility/cmd_show.c @@ -419,6 +419,7 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state) int retval = 0; uint64_t vmlinuz_header_size = 0; uint64_t vmlinuz_header_address = 0; + uint32_t flags = 0; /* Check the hash... */ if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) { @@ -483,6 +484,10 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state) vmlinuz_header_size); } + if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) + flags = preamble->flags; + printf(" Flags: 0x%" PRIx32 "\n", flags); + /* Verify kernel body */ if (option.fv) { /* It's in a separate file, which we've already read in */ diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c index a960abd6..2d247bcd 100644 --- a/futility/cmd_sign.c +++ b/futility/cmd_sign.c @@ -219,7 +219,7 @@ int futil_cb_create_kernel_part(struct futil_traverse_state_s *state) vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, option.version, option.kloadaddr, option.keyblock, option.signprivate, - &vblock_size); + option.flags, &vblock_size); if (!vblock_data) { fprintf(stderr, "Unable to sign kernel blob\n"); free(kblob_data); @@ -288,6 +288,12 @@ int futil_cb_resign_kernel_part(struct futil_traverse_state_s *state) if (!option.version_specified) option.version = preamble->kernel_version; + /* Preserve the flags if not specified */ + if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) { + if (option.flags_specified == 0) + option.flags = preamble->flags; + } + /* Replace the keyblock if asked */ if (option.keyblock) keyblock = option.keyblock; @@ -296,7 +302,7 @@ int futil_cb_resign_kernel_part(struct futil_traverse_state_s *state) vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, option.version, option.kloadaddr, keyblock, option.signprivate, - &vblock_size); + option.flags, &vblock_size); if (!vblock_data) { fprintf(stderr, "Unable to sign kernel blob\n"); return 1; @@ -612,7 +618,8 @@ static const char usage_new_kpart[] = "\n" " --pad NUM The vblock padding size in bytes\n" " (default 0x%x)\n" " --vblockonly Emit just the vblock (requires a\n" - " distinct outfile)\n"; + " distinct outfile)\n" + " -f|--flags NUM The preamble flags value\n"; static const char usage_old_kpart[] = "\n" "-----------------------------------------------------------------\n" @@ -634,6 +641,7 @@ static const char usage_old_kpart[] = "\n" " [--outfile] OUTFILE Output kernel partition or vblock\n" " --vblockonly Emit just the vblock (requires a\n" " distinct OUTFILE)\n" + " -f|--flags NUM The preamble flags value\n" "\n"; static void print_help(const char *prog) diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c index ae4fd3f9..3322e4b8 100644 --- a/futility/cmd_vbutil_kernel.c +++ b/futility/cmd_vbutil_kernel.c @@ -63,6 +63,7 @@ enum { OPT_VERBOSE, OPT_MINVERSION, OPT_VMLINUZ_OUT, + OPT_FLAGS, }; static const struct option long_opts[] = { @@ -86,6 +87,7 @@ static const struct option long_opts[] = { {"verbose", 0, &opt_verbose, 1}, {"debug", 0, &debugging_enabled, 1}, {"vmlinuz-out", 1, 0, OPT_VMLINUZ_OUT}, + {"flags", 1, 0, OPT_FLAGS}, {NULL, 0, 0, 0} }; @@ -109,6 +111,7 @@ static const char usage[] = " --kloadaddr <address> Assign kernel body load address\n" " --pad <number> Verification padding size in bytes\n" " --vblockonly Emit just the verification blob\n" + " --flags NUM Flags to be passed in the header\n" "\nOR\n\n" "Usage: " MYNAME " %s --repack <file> [PARAMETERS]\n" "\n" @@ -253,6 +256,7 @@ static int do_vbutil_kernel(int argc, char *argv[]) uint64_t kblob_size = 0; uint8_t *vblock_data = NULL; uint64_t vblock_size = 0; + uint32_t flags = 0; FILE *f; while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) && @@ -328,6 +332,14 @@ static int do_vbutil_kernel(int argc, char *argv[]) vmlinuz_file = optarg; break; + case OPT_FLAGS: + flags = (uint32_t)strtoul(optarg, &e, 0); + if (!*optarg || (e && *e)) { + fprintf(stderr, "Invalid --flags\n"); + parse_error = 1; + } + break; + case OPT_BOOTLOADER: bootloader_file = optarg; break; @@ -435,7 +447,7 @@ static int do_vbutil_kernel(int argc, char *argv[]) vblock_data = SignKernelBlob(kblob_data, kblob_size, opt_pad, version, kernel_body_load_address, - t_keyblock, signpriv_key, + t_keyblock, signpriv_key, flags, &vblock_size); if (!vblock_data) Fatal("Unable to sign kernel blob\n"); @@ -498,6 +510,9 @@ static int do_vbutil_kernel(int argc, char *argv[]) if (!version_str) version = preamble->kernel_version; + if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) + flags = preamble->flags; + if (keyblock_file) { t_keyblock = (VbKeyBlockHeader *)ReadFile(keyblock_file, 0); @@ -509,7 +524,7 @@ static int do_vbutil_kernel(int argc, char *argv[]) vblock_data = SignKernelBlob(kblob_data, kblob_size, opt_pad, version, kernel_body_load_address, t_keyblock ? t_keyblock : keyblock, - signpriv_key, &vblock_size); + signpriv_key, flags, &vblock_size); if (!vblock_data) Fatal("Unable to sign kernel blob\n"); diff --git a/futility/vb1_helper.c b/futility/vb1_helper.c index f40b7ac8..3d3225a1 100644 --- a/futility/vb1_helper.c +++ b/futility/vb1_helper.c @@ -305,6 +305,7 @@ uint8_t *UnpackKPart(uint8_t *kpart_data, uint64_t kpart_size, uint64_t vmlinuz_header_size = 0; uint64_t vmlinuz_header_address = 0; uint64_t now = 0; + uint32_t flags = 0; /* Sanity-check the keyblock */ keyblock = (VbKeyBlockHeader *)kpart_data; @@ -347,6 +348,11 @@ uint8_t *UnpackKPart(uint8_t *kpart_data, uint64_t kpart_size, Debug(" bootloader_size = 0x%" PRIx64 "\n", preamble->bootloader_size); Debug(" kern_blob_size = 0x%" PRIx64 "\n", preamble->body_signature.data_size); + + if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) + flags = preamble->flags; + Debug(" flags = 0x%" PRIx32 "\n", flags); + g_preamble = preamble; g_ondisk_bootloader_addr = g_preamble->bootloader_address; @@ -392,7 +398,7 @@ uint8_t *SignKernelBlob(uint8_t *kernel_blob, uint64_t kernel_size, uint64_t padding, int version, uint64_t kernel_body_load_address, VbKeyBlockHeader *keyblock, VbPrivateKey *signpriv_key, - uint64_t *vblock_size_ptr) + uint32_t flags, uint64_t *vblock_size_ptr) { VbSignature *body_sig; VbKernelPreambleHeader *preamble; @@ -416,6 +422,7 @@ uint8_t *SignKernelBlob(uint8_t *kernel_blob, uint64_t kernel_size, body_sig, g_ondisk_vmlinuz_header_addr, g_vmlinuz_header_size, + flags, min_size, signpriv_key); if (!preamble) { @@ -591,6 +598,10 @@ int VerifyKernelBlob(uint8_t *kernel_blob, vmlinuz_header_size); } + if (VbKernelHasFlags(g_preamble) == VBOOT_SUCCESS) + printf(" Flags : 0x%" PRIx32 "\n", + g_preamble->flags); + if (g_preamble->kernel_version < (min_version & 0xFFFF)) { fprintf(stderr, "Kernel version %" PRIu64 " is lower than minimum %" diff --git a/futility/vb1_helper.h b/futility/vb1_helper.h index fd976e0e..2cf71f4e 100644 --- a/futility/vb1_helper.h +++ b/futility/vb1_helper.h @@ -18,7 +18,7 @@ uint8_t *SignKernelBlob(uint8_t *kernel_blob, uint64_t kernel_size, uint64_t padding, int version, uint64_t kernel_body_load_address, VbKeyBlockHeader *keyblock, VbPrivateKey *signpriv_key, - uint64_t *vblock_size_ptr); + uint32_t flags, uint64_t *vblock_size_ptr); int WriteSomeParts(const char *outfile, void *part1_data, uint64_t part1_size, diff --git a/host/lib/host_common.c b/host/lib/host_common.c index b9c00cde..959b65a6 100644 --- a/host/lib/host_common.c +++ b/host/lib/host_common.c @@ -78,6 +78,7 @@ VbKernelPreambleHeader *CreateKernelPreamble( const VbSignature *body_signature, uint64_t vmlinuz_header_address, uint64_t vmlinuz_header_size, + uint32_t flags, uint64_t desired_size, const VbPrivateKey *signing_key) { @@ -111,6 +112,7 @@ VbKernelPreambleHeader *CreateKernelPreamble( h->bootloader_size = bootloader_size; h->vmlinuz_header_address = vmlinuz_header_address; h->vmlinuz_header_size = vmlinuz_header_size; + h->flags = flags; /* Copy body signature */ SignatureInit(&h->body_signature, body_sig_dest, diff --git a/host/lib/include/host_common.h b/host/lib/include/host_common.h index b4693f84..895a675f 100644 --- a/host/lib/include/host_common.h +++ b/host/lib/include/host_common.h @@ -52,6 +52,7 @@ VbKernelPreambleHeader *CreateKernelPreamble( const VbSignature *body_signature, uint64_t vmlinuz_header_address, uint64_t vmlinuz_header_size, + uint32_t flags, uint64_t desired_size, const VbPrivateKey *signing_key); diff --git a/host/linktest/main.c b/host/linktest/main.c index e24d5579..8e1525fa 100644 --- a/host/linktest/main.c +++ b/host/linktest/main.c @@ -41,7 +41,7 @@ int main(void) /* host_common.h */ CreateFirmwarePreamble(0, 0, 0, 0, 0); - CreateKernelPreamble(0, 0, 0, 0, 0, 0, 0, 0, 0); + CreateKernelPreamble(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); /* file_keys.h */ BufferFromFile(0, 0); diff --git a/tests/vboot_common2_tests.c b/tests/vboot_common2_tests.c index 3a2b59f3..40953117 100644 --- a/tests/vboot_common2_tests.c +++ b/tests/vboot_common2_tests.c @@ -128,7 +128,7 @@ static void VerifyKernelPreambleTest(const VbPublicKey *public_key, rsa = PublicKeyToRSA(public_key); hdr = CreateKernelPreamble(0x1234, 0x100000, 0x300000, 0x4000, body_sig, - 0, 0, 0, private_key); + 0, 0, 0, 0, private_key); TEST_NEQ(hdr && rsa, 0, "VerifyKernelPreamble() prerequisites"); if (!hdr) return; diff --git a/tests/vboot_common_tests.c b/tests/vboot_common_tests.c index 8fd021a1..3c303a6c 100644 --- a/tests/vboot_common_tests.c +++ b/tests/vboot_common_tests.c @@ -31,7 +31,7 @@ static void StructPackingTest(void) TEST_EQ(EXPECTED_VBFIRMWAREPREAMBLEHEADER2_1_SIZE, sizeof(VbFirmwarePreambleHeader), "sizeof(VbFirmwarePreambleHeader)"); - TEST_EQ(EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE, + TEST_EQ(EXPECTED_VBKERNELPREAMBLEHEADER2_2_SIZE, sizeof(VbKernelPreambleHeader), "sizeof(VbKernelPreambleHeader)"); |