115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson/* 215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson * Copyright 2014 The Chromium OS Authors. All rights reserved. 315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson * Use of this source code is governed by a BSD-style license that can be 415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson * found in the LICENSE file. 515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson */ 615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <errno.h> 715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <fcntl.h> 815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <getopt.h> 915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <inttypes.h> 1015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <limits.h> 1115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <stddef.h> 1215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <stdint.h> 1315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <stdio.h> 1415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <stdlib.h> 1515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <string.h> 1615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <sys/stat.h> 1715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <sys/types.h> 1815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include <unistd.h> 1915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 2015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include "bmpblk_header.h" 212559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include "file_type.h" 2215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include "fmap.h" 2315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include "futility.h" 2415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include "gbb_header.h" 2515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include "host_common.h" 265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson#include "kernel_blob.h" 2715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include "traversal.h" 2815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include "util_misc.h" 295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson#include "vb1_helper.h" 3015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson#include "vboot_common.h" 3115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 3215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson/* Local values for cb_area_s._flags */ 3315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonenum callback_flags { 3415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson AREA_IS_VALID = 0x00000001, 3515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson}; 3615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 3715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson/* Local structure for args, etc. */ 385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonstatic struct local_data_s { 3915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbPrivateKey *signprivate; 4015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbKeyBlockHeader *keyblock; 4115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbPublicKey *kernel_subkey; 4215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbPrivateKey *devsignprivate; 4315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbKeyBlockHeader *devkeyblock; 4415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson uint32_t version; 455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int version_specified; 4615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson uint32_t flags; 47a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson int flags_specified; 4815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson char *loemdir; 4915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson char *loemid; 505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *bootloader_data; 515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t bootloader_size; 525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *config_data; 535f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t config_size; 545f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson enum arch_t arch; 55c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson int fv_specified; 565f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint32_t kloadaddr; 575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint32_t padding; 585f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int vblockonly; 595f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson char *outfile; 605f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int create_new_outfile; 61c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson char *pem_signpriv; 62c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson int pem_algo_specified; 63c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson uint32_t pem_algo; 64c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson char *pem_external; 6515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} option = { 6615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson .version = 1, 675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson .arch = ARCH_UNSPECIFIED, 685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson .kloadaddr = CROS_32BIT_ENTRY_ADDR, 695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson .padding = 65536, 7015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson}; 7115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 7215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 735f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson/* Helper to complain about invalid args. Returns num errors discovered */ 745f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonstatic int no_opt_if(int expr, const char *optname) 7515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 765f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (expr) { 775f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Missing --%s option\n", optname); 785f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 0; 8115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 8215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson/* This wraps/signs a public key, producing a keyblock. */ 845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_sign_pubkey(struct futil_traverse_state_s *state) 8515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 86c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson VbPublicKey *data_key = (VbPublicKey *)state->my_area->buf; 87c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson VbKeyBlockHeader *vblock; 88c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 89c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if (option.pem_signpriv) { 90c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if (option.pem_external) { 91c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson /* External signing uses the PEM file directly. */ 92c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson vblock = KeyBlockCreate_external( 93c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson data_key, 94c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.pem_signpriv, 95c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.pem_algo, option.flags, 96c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.pem_external); 97c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } else { 98c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.signprivate = PrivateKeyReadPem( 99c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.pem_signpriv, option.pem_algo); 100c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if (!option.signprivate) { 101c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson fprintf(stderr, 102c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "Unable to read PEM signing key: %s\n", 103c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson strerror(errno)); 104c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson return 1; 105c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 106c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson vblock = KeyBlockCreate(data_key, option.signprivate, 107c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.flags); 108c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 109c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } else { 110c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson /* Not PEM. Should already have a signing key. */ 111c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson vblock = KeyBlockCreate(data_key, option.signprivate, 112c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.flags); 113c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 114c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 115c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson /* Write it out */ 116c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson return WriteSomeParts(option.outfile, 117c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson vblock, vblock->key_block_size, 118c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson NULL, 0); 11915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 12015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 12115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson/* 12215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image. 12315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson * The data in state->my_area is just the RW firmware blob, so there's nothing 12415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson * useful to show about it. We'll just mark it as present so when we encounter 12515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson * corresponding VBLOCK area, we'll have this to verify. 12615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson */ 12715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonint futil_cb_sign_fw_main(struct futil_traverse_state_s *state) 12815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 12915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 13015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 0; 13115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 13215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 133779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson/* 134779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson * This handles VBLOCK_A and VBLOCK_B while processing a BIOS image. 135779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson * We don't do any signing here. We just check to see if the VBLOCK 136779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson * area contains a firmware preamble. 137779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson */ 1385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_sign_fw_vblock(struct futil_traverse_state_s *state) 13915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 14015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf; 141e051975c900caf43046a97cda682629915c62c7eBill Richardson uint32_t len = state->my_area->len; 14215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 14315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson /* 144e051975c900caf43046a97cda682629915c62c7eBill Richardson * If we have a valid keyblock and fw_preamble, then we can use them to 145e051975c900caf43046a97cda682629915c62c7eBill Richardson * determine the size of the firmware body. Otherwise, we'll have to 146e051975c900caf43046a97cda682629915c62c7eBill Richardson * just sign the whole region. 14715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson */ 148e051975c900caf43046a97cda682629915c62c7eBill Richardson if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) { 149e051975c900caf43046a97cda682629915c62c7eBill Richardson fprintf(stderr, "Warning: %s keyblock is invalid. " 150e051975c900caf43046a97cda682629915c62c7eBill Richardson "Signing the entire FW FMAP region...\n", 151779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson state->name); 152e051975c900caf43046a97cda682629915c62c7eBill Richardson goto whatever; 153e051975c900caf43046a97cda682629915c62c7eBill Richardson } 15415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 155e051975c900caf43046a97cda682629915c62c7eBill Richardson RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); 156e051975c900caf43046a97cda682629915c62c7eBill Richardson if (!rsa) { 157e051975c900caf43046a97cda682629915c62c7eBill Richardson fprintf(stderr, "Warning: %s public key is invalid. " 158e051975c900caf43046a97cda682629915c62c7eBill Richardson "Signing the entire FW FMAP region...\n", 159e051975c900caf43046a97cda682629915c62c7eBill Richardson state->name); 160e051975c900caf43046a97cda682629915c62c7eBill Richardson goto whatever; 161e051975c900caf43046a97cda682629915c62c7eBill Richardson } 16215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson uint32_t more = key_block->key_block_size; 16315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbFirmwarePreambleHeader *preamble = 16415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson (VbFirmwarePreambleHeader *)(state->my_area->buf + more); 16515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson uint32_t fw_size = preamble->body_signature.data_size; 166e051975c900caf43046a97cda682629915c62c7eBill Richardson struct cb_area_s *fw_body_area = 0; 16715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 16815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson switch (state->component) { 16915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case CB_FMAP_VBLOCK_A: 17015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_A]; 17108efd1ee358c546c968918a24b45219d7003cecaBill Richardson /* Preserve the flags if they're not specified */ 172a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson if (!option.flags_specified) 17308efd1ee358c546c968918a24b45219d7003cecaBill Richardson option.flags = preamble->flags; 17415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 17515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case CB_FMAP_VBLOCK_B: 17615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_B]; 17715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 17815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson default: 17915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson DIE; 18015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 18115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 18215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (fw_size > fw_body_area->len) { 18315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, 18415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "%s says the firmware is larger than we have\n", 185779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson state->name); 18615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 18715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 18815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 18915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson /* Update the firmware size */ 19015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fw_body_area->len = fw_size; 19115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 192e051975c900caf43046a97cda682629915c62c7eBill Richardsonwhatever: 19315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 19415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 19515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 0; 19615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 19715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 1985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_create_kernel_part(struct futil_traverse_state_s *state) 1995f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson{ 2005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *vmlinuz_data, *kblob_data, *vblock_data; 2015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t vmlinuz_size, kblob_size, vblock_size; 2025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int rv; 2035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson vmlinuz_data = state->my_area->buf; 2055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson vmlinuz_size = state->my_area->len; 2065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kblob_data = CreateKernelBlob( 2085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson vmlinuz_data, vmlinuz_size, 2095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.arch, option.kloadaddr, 2105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.config_data, option.config_size, 2115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.bootloader_data, option.bootloader_size, 2125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson &kblob_size); 2135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!kblob_data) { 2145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Unable to create kernel blob\n"); 2155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 2165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 2175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson Debug("kblob_size = 0x%" PRIx64 "\n", kblob_size); 2185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, 2205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.version, option.kloadaddr, 2215f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.keyblock, option.signprivate, 22280e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh option.flags, &vblock_size); 2235f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!vblock_data) { 2245f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Unable to sign kernel blob\n"); 2255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson free(kblob_data); 2265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 2275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 2285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson Debug("vblock_size = 0x%" PRIx64 "\n", vblock_size); 2295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* We should be creating a completely new output file. 2315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson * If not, something's wrong. */ 2325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!option.create_new_outfile) 2335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson DIE; 2345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.vblockonly) 2365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson rv = WriteSomeParts(option.outfile, 2375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson vblock_data, vblock_size, 2385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson NULL, 0); 2395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson else 2405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson rv = WriteSomeParts(option.outfile, 2415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson vblock_data, vblock_size, 2425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kblob_data, kblob_size); 2435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson free(vblock_data); 2455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson free(kblob_data); 2465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return rv; 2475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} 2485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_resign_kernel_part(struct futil_traverse_state_s *state) 2505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson{ 2515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *kpart_data, *kblob_data, *vblock_data; 2525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t kpart_size, kblob_size, vblock_size; 2535f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbKeyBlockHeader *keyblock = NULL; 2545f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbKernelPreambleHeader *preamble = NULL; 2555f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int rv = 0; 2565f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kpart_data = state->my_area->buf; 2585f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kpart_size = state->my_area->len; 2595f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2605f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Note: This just sets some static pointers. It doesn't malloc. */ 2615f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kblob_data = UnpackKPart(kpart_data, kpart_size, option.padding, 2625f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson &keyblock, &preamble, &kblob_size); 2635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!kblob_data) { 2655f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Unable to unpack kernel partition\n"); 2665f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 2675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 2685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* 2705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson * We don't let --kloadaddr change when resigning, because the original 2715f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson * vbutil_kernel program didn't do it right. Since obviously no one 2725f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson * ever noticed, we'll maintain bug-compatibility by just not allowing 2735f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson * it here either. To enable it, we'd need to update the zeropage 2745f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson * table's cmd_line_ptr as well as the preamble. 2755f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson */ 2765f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.kloadaddr = preamble->body_load_address; 2775f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2785f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Replace the config if asked */ 2795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.config_data && 2805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 0 != UpdateKernelBlobConfig(kblob_data, kblob_size, 2815f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.config_data, 2825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.config_size)) { 2835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Unable to update config\n"); 2845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 2855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 2865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 2875f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Preserve the version unless a new one is given */ 2885f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!option.version_specified) 2895f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.version = preamble->kernel_version; 2905f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 29180e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh /* Preserve the flags if not specified */ 29280e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) { 29380e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh if (option.flags_specified == 0) 29480e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh option.flags = preamble->flags; 29580e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh } 29680e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh 2975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Replace the keyblock if asked */ 2985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.keyblock) 2995f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson keyblock = option.keyblock; 3005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Compute the new signature */ 3025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, 3035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.version, option.kloadaddr, 3045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson keyblock, option.signprivate, 30580e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh option.flags, &vblock_size); 3065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!vblock_data) { 3075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Unable to sign kernel blob\n"); 3085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 3095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 3105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson Debug("vblock_size = 0x%" PRIx64 "\n", vblock_size); 3115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 312b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson if (option.create_new_outfile) { 313b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson /* Write out what we've been asked for */ 314b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson if (option.vblockonly) 315b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson rv = WriteSomeParts(option.outfile, 316b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson vblock_data, vblock_size, 317b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson NULL, 0); 318b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson else 319b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson rv = WriteSomeParts(option.outfile, 320b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson vblock_data, vblock_size, 321b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson kblob_data, kblob_size); 3225f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } else { 323b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson /* If we're modifying an existing file, it's mmap'ed so that 324b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson * all our modifications to the buffer will get flushed to 325b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson * disk when we close it. */ 3265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson Memcpy(kpart_data, vblock_data, vblock_size); 3275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 3285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson free(vblock_data); 3305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return rv; 3315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} 3325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_sign_raw_firmware(struct futil_traverse_state_s *state) 3355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson{ 336c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson VbSignature *body_sig; 337c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson VbFirmwarePreambleHeader *preamble; 338c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson int rv; 339c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 340c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson body_sig = CalculateSignature(state->my_area->buf, state->my_area->len, 341c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.signprivate); 342c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if (!body_sig) { 343c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson fprintf(stderr, "Error calculating body signature\n"); 344c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson return 1; 345c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 346c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 347c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson preamble = CreateFirmwarePreamble(option.version, 348c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.kernel_subkey, 349c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson body_sig, 350c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.signprivate, 351c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.flags); 352c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if (!preamble) { 353c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson fprintf(stderr, "Error creating firmware preamble.\n"); 354c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson free(body_sig); 355c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson return 1; 356c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 357c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 358c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson rv = WriteSomeParts(option.outfile, 359c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.keyblock, option.keyblock->key_block_size, 360c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson preamble, preamble->preamble_size); 361c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 362c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson free(preamble); 363c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson free(body_sig); 364c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 365c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson return rv; 3665f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} 3675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 36915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonint futil_cb_sign_begin(struct futil_traverse_state_s *state) 37015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 37115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (state->in_type == FILE_TYPE_UNKNOWN) { 37215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Unable to determine type of %s\n", 37315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson state->in_filename); 37415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 37515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 37615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 37715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 0; 37815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 37915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 38015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonstatic int write_new_preamble(struct cb_area_s *vblock, 38115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson struct cb_area_s *fw_body, 38215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbPrivateKey *signkey, 38315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbKeyBlockHeader *keyblock) 38415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 38515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbSignature *body_sig; 38615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson VbFirmwarePreambleHeader *preamble; 38715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 38815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson body_sig = CalculateSignature(fw_body->buf, fw_body->len, signkey); 38915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!body_sig) { 39015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Error calculating body signature\n"); 39115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 39215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 39315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 39415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson preamble = CreateFirmwarePreamble(option.version, 39515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.kernel_subkey, 39615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson body_sig, 39715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson signkey, 39815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.flags); 39915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!preamble) { 40015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Error creating firmware preamble.\n"); 40115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson free(body_sig); 40215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 40315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 40415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 40515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson /* Write the new keyblock */ 40615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson uint32_t more = keyblock->key_block_size; 40715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson memcpy(vblock->buf, keyblock, more); 40815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson /* and the new preamble */ 40915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson memcpy(vblock->buf + more, preamble, preamble->preamble_size); 41015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 41115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson free(preamble); 41215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson free(body_sig); 41315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 41415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 0; 41515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 41615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 41715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonstatic int write_loem(const char *ab, struct cb_area_s *vblock) 41815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 41915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson char filename[PATH_MAX]; 42015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson int n; 42115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson n = snprintf(filename, sizeof(filename), "%s/vblock_%s.%s", 42215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.loemdir ? option.loemdir : ".", 42315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson ab, option.loemid); 42415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (n >= sizeof(filename)) { 42515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "LOEM args produce bogus filename\n"); 42615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 42715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 42815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 42915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson FILE *fp = fopen(filename, "w"); 43015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!fp) { 43115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Can't open %s for writing: %s\n", 43215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson filename, strerror(errno)); 43315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 43415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 43515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 43615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (1 != fwrite(vblock->buf, vblock->len, 1, fp)) { 43715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Can't write to %s: %s\n", 43815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson filename, strerror(errno)); 43915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fclose(fp); 44015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 44115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 44215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (fclose(fp)) { 44315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Failed closing loem output: %s\n", 44415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson strerror(errno)); 44515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 44615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 44715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 44815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 0; 44915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 45015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 4515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson/* This signs a full BIOS image after it's been traversed. */ 4525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonstatic int sign_bios_at_end(struct futil_traverse_state_s *state) 45315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 45415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson struct cb_area_s *vblock_a = &state->cb_area[CB_FMAP_VBLOCK_A]; 45515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson struct cb_area_s *vblock_b = &state->cb_area[CB_FMAP_VBLOCK_B]; 45615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson struct cb_area_s *fw_a = &state->cb_area[CB_FMAP_FW_MAIN_A]; 45715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson struct cb_area_s *fw_b = &state->cb_area[CB_FMAP_FW_MAIN_B]; 45815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson int retval = 0; 45915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 46015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (state->errors || 46115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson !(vblock_a->_flags & AREA_IS_VALID) || 46215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson !(vblock_b->_flags & AREA_IS_VALID) || 46315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson !(fw_a->_flags & AREA_IS_VALID) || 46415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson !(fw_b->_flags & AREA_IS_VALID)) { 46515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Something's wrong. Not changing anything\n"); 46615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 46715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 46815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 46915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson /* Do A & B differ ? */ 47015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (fw_a->len != fw_b->len || 47115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson memcmp(fw_a->buf, fw_b->buf, fw_a->len)) { 47215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson /* Yes, must use DEV keys for A */ 47315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!option.devsignprivate || !option.devkeyblock) { 47415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, 47515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "FW A & B differ. DEV keys are required.\n"); 47615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return 1; 47715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 47815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson retval |= write_new_preamble(vblock_a, fw_a, 47915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.devsignprivate, 48015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.devkeyblock); 48115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } else { 48215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson retval |= write_new_preamble(vblock_a, fw_a, 48315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.signprivate, 48415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.keyblock); 48515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 48615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 48715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson /* FW B is always normal keys */ 48815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson retval |= write_new_preamble(vblock_b, fw_b, 48915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.signprivate, 49015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.keyblock); 49115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 49215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 49315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 49415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 49515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (option.loemid) { 49615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson retval |= write_loem("A", vblock_a); 49715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson retval |= write_loem("B", vblock_b); 49815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 49915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 50015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return retval; 50115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 50215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 5035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_sign_end(struct futil_traverse_state_s *state) 5045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson{ 5055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson switch (state->in_type) { 5065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_BIOS_IMAGE: 5075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_OLD_BIOS_IMAGE: 5085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return sign_bios_at_end(state); 5095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 5105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson default: 5115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Any other cleanup needed? */ 5125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 5135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 5145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 5155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return state->errors; 5165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} 5175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 51815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonstatic const char usage[] = "\n" 5195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Usage: " MYNAME " %s [PARAMS] INFILE [OUTFILE]\n" 52015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "\n" 5215f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Where INFILE is a\n" 5225f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "\n" 523c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " public key (.vbpubk); OUTFILE is a keyblock\n" 524c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " raw firmware blob (FW_MAIN_A/B); OUTFILE is a VBLOCK_A/B\n" 5255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " complete firmware image (bios.bin)\n" 5265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " raw linux kernel; OUTFILE is a kernel partition image\n" 5275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " kernel partition image (/dev/sda2, /dev/mmcblk0p2)\n"; 5285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 529c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardsonstatic const char usage_pubkey[] = "\n" 530c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "-----------------------------------------------------------------\n" 531c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "To sign a public key / create a new keyblock:\n" 532c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "\n" 533c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "Required PARAMS:\n" 534c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " [--datapubkey] INFILE The public key to wrap\n" 535c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " [--outfile] OUTFILE The resulting keyblock\n" 536c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "\n" 537c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "Optional PARAMS:\n" 538c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " A private signing key, specified as either\n" 539c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " -s|--signprivate FILE.vbprivk Signing key in .vbprivk format\n" 540c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " Or\n" 541c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " --pem_signpriv FILE.pem Signing key in PEM format...\n" 542c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " --pem_algo NUM AND the algorithm to use (0 - %d)\n" 543c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "\n" 544c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " If a signing key is not given, the keyblock will not be signed (duh)." 545c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "\n\n" 546c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "And these, too:\n\n" 547c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " -f|--flags NUM Flags specifying use conditions\n" 548c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " --pem_external PROGRAM" 549c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " External program to compute the signature\n" 550c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " (requires a PEM signing key)\n"; 551c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 552c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardsonstatic const char usage_fw_main[] = "\n" 553c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "-----------------------------------------------------------------\n" 554c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "To sign a raw firmware blob (FW_MAIN_A/B):\n" 555c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "\n" 556c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "Required PARAMS:\n" 557c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " -s|--signprivate FILE.vbprivk The private firmware data key\n" 558c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " -b|--keyblock FILE.keyblock The keyblock containing the\n" 559c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " public firmware data key\n" 560c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " -k|--kernelkey FILE.vbpubk The public kernel subkey\n" 561c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " -v|--version NUM The firmware version number\n" 562c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " [--fv] INFILE" 563c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " The raw firmware blob (FW_MAIN_A/B)\n" 564c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " [--outfile] OUTFILE Output VBLOCK_A/B\n" 565c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "\n" 566c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "Optional PARAMS:\n" 567c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " -f|--flags NUM The preamble flags value" 568c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " (default is 0)\n"; 569c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 5705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonstatic const char usage_bios[] = "\n" 5715f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "-----------------------------------------------------------------\n" 5725f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "To sign a complete firmware image (bios.bin):\n" 57315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "\n" 5745f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Required PARAMS:\n" 57515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " -s|--signprivate FILE.vbprivk The private firmware data key\n" 57615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " -b|--keyblock FILE.keyblock The keyblock containing the\n" 57715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " public firmware data key\n" 57815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " -k|--kernelkey FILE.vbpubk The public kernel subkey\n" 5795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " [--infile] INFILE Input firmware image (modified\n" 5805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " in place if no OUTFILE given)\n" 58115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "\n" 58215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "These are required if the A and B firmware differ:\n" 58315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " -S|--devsign FILE.vbprivk The DEV private firmware data key\n" 58415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " -B|--devkeyblock FILE.keyblock The keyblock containing the\n" 58515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " DEV public firmware data key\n" 58615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "\n" 5875f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Optional PARAMS:\n" 58808efd1ee358c546c968918a24b45219d7003cecaBill Richardson " -v|--version NUM The firmware version number" 58908efd1ee358c546c968918a24b45219d7003cecaBill Richardson " (default %d)\n" 59008efd1ee358c546c968918a24b45219d7003cecaBill Richardson " -f|--flags NUM The preamble flags value" 59108efd1ee358c546c968918a24b45219d7003cecaBill Richardson " (default is\n" 59208efd1ee358c546c968918a24b45219d7003cecaBill Richardson " unchanged, or 0 if unknown)\n" 59315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " -d|--loemdir DIR Local OEM output vblock directory\n" 59415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson " -l|--loemid STRING Local OEM vblock suffix\n" 5955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " [--outfile] OUTFILE Output firmware image\n"; 5965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 5975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonstatic const char usage_new_kpart[] = "\n" 5985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "-----------------------------------------------------------------\n" 5995f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "To create a new kernel parition image (/dev/sda2, /dev/mmcblk0p2):\n" 6005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "\n" 6015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Required PARAMS:\n" 6025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -s|--signprivate FILE.vbprivk" 6035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " The private key to sign the kernel blob\n" 6045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -b|--keyblock FILE.keyblock The keyblock containing the public\n" 6055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " key to verify the kernel blob\n" 6065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -v|--version NUM The kernel version number\n" 6075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --bootloader FILE Bootloader stub\n" 6085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --config FILE The kernel commandline file\n" 6095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --arch ARCH The CPU architecture (one of\n" 6105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " x86|amd64, arm|aarch64, mips)\n" 6115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " [--vmlinuz] INFILE Linux kernel bzImage file\n" 6125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " [--outfile] OUTFILE Output kernel partition or vblock\n" 6135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "\n" 6145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Optional PARAMS:\n" 6155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --kloadaddr NUM" 6165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " RAM address to load the kernel body\n" 6175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " (default 0x%x)\n" 6185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --pad NUM The vblock padding size in bytes\n" 6195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " (default 0x%x)\n" 6205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --vblockonly Emit just the vblock (requires a\n" 62180e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh " distinct outfile)\n" 62280e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh " -f|--flags NUM The preamble flags value\n"; 6235f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 6245f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonstatic const char usage_old_kpart[] = "\n" 6255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "-----------------------------------------------------------------\n" 6265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "To resign an existing kernel parition (/dev/sda2, /dev/mmcblk0p2):\n" 6275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "\n" 6285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Required PARAMS:\n" 6295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -s|--signprivate FILE.vbprivk" 6305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " The private key to sign the kernel blob\n" 6315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " [--infile] INFILE Input kernel partition (modified\n" 6325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " in place if no OUTFILE given)\n" 6335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "\n" 6345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Optional PARAMS:\n" 6355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -b|--keyblock FILE.keyblock The keyblock containing the public\n" 6365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " key to verify the kernel blob\n" 6375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -v|--version NUM The kernel version number\n" 6385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --config FILE The kernel commandline file\n" 6395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --pad NUM The vblock padding size in bytes\n" 6405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " (default 0x%x)\n" 6415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " [--outfile] OUTFILE Output kernel partition or vblock\n" 6425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --vblockonly Emit just the vblock (requires a\n" 6435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " distinct OUTFILE)\n" 64480e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh " -f|--flags NUM The preamble flags value\n" 64515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "\n"; 64615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 647779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *prog) 64815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 6495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(usage, prog); 650c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson printf(usage_pubkey, kNumAlgorithms - 1); 651c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson puts(usage_fw_main); 6525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(usage_bios, option.version); 6535f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(usage_new_kpart, option.kloadaddr, option.padding); 6545f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(usage_old_kpart, option.padding); 65515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 65615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 6575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonenum no_short_opts { 6585f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_FV = 1000, 6595f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_INFILE, /* aka "--vmlinuz" */ 6605f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_OUTFILE, 6615f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_BOOTLOADER, 6625f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_CONFIG, 6635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_ARCH, 6645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_KLOADADDR, 6655f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_PADDING, 666c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson OPT_PEM_SIGNPRIV, 667c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson OPT_PEM_ALGO, 668c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson OPT_PEM_EXTERNAL, 6695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson}; 6705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 67115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonstatic const struct option long_opts[] = { 67215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson /* name hasarg *flag val */ 6735f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"signprivate", 1, NULL, 's'}, 6745f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"keyblock", 1, NULL, 'b'}, 6755f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"kernelkey", 1, NULL, 'k'}, 6765f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"devsign", 1, NULL, 'S'}, 6775f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"devkeyblock", 1, NULL, 'B'}, 6785f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"version", 1, NULL, 'v'}, 6795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"flags", 1, NULL, 'f'}, 6805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"loemdir", 1, NULL, 'd'}, 6815f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"loemid", 1, NULL, 'l'}, 6825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"fv", 1, NULL, OPT_FV}, 6835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"infile", 1, NULL, OPT_INFILE}, 6845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"datapubkey", 1, NULL, OPT_INFILE}, /* alias */ 6855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"vmlinuz", 1, NULL, OPT_INFILE}, /* alias */ 6865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"outfile", 1, NULL, OPT_OUTFILE}, 6875f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"bootloader", 1, NULL, OPT_BOOTLOADER}, 6885f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"config", 1, NULL, OPT_CONFIG}, 6895f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"arch", 1, NULL, OPT_ARCH}, 6905f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"kloadaddr", 1, NULL, OPT_KLOADADDR}, 6915f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"pad", 1, NULL, OPT_PADDING}, 692c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson {"pem_signpriv", 1, NULL, OPT_PEM_SIGNPRIV}, 693c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson {"pem_algo", 1, NULL, OPT_PEM_ALGO}, 694c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson {"pem_external", 1, NULL, OPT_PEM_EXTERNAL}, 6955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"vblockonly", 0, &option.vblockonly, 1}, 6965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"debug", 0, &debugging_enabled, 1}, 6975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {NULL, 0, NULL, 0}, 69815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson}; 69915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonstatic char *short_opts = ":s:b:k:S:B:v:f:d:l:"; 70015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 70115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardsonstatic int do_sign(int argc, char *argv[]) 70215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson{ 70315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson char *infile = 0; 7045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int i; 7055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int ifd = -1; 70615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson int errorcnt = 0; 70715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson struct futil_traverse_state_s state; 708b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson uint8_t *buf; 709b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson uint32_t buf_len; 7105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson char *e = 0; 7115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson enum futil_file_type type; 7125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int inout_file_count = 0; 7135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int mapping; 71415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 71515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson opterr = 0; /* quiet, you */ 71615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { 71715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson switch (i) { 71815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 's': 71915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.signprivate = PrivateKeyRead(optarg); 72015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!option.signprivate) { 72115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 72215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 72315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 72415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 72515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 'b': 72615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.keyblock = KeyBlockRead(optarg); 72715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!option.keyblock) { 72815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 72915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 73015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 73115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 73215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 'k': 73315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.kernel_subkey = PublicKeyRead(optarg); 73415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!option.kernel_subkey) { 73515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 73615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 73715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 73815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 73915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 'S': 74015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.devsignprivate = PrivateKeyRead(optarg); 74115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!option.devsignprivate) { 74215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 74315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 74415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 74515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 74615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 'B': 74715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.devkeyblock = KeyBlockRead(optarg); 74815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!option.devkeyblock) { 74915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 75015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 75115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 75215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 75315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 'v': 7545f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.version_specified = 1; 75515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.version = strtoul(optarg, &e, 0); 75615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!*optarg || (e && *e)) { 75715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, 75815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "Invalid --version \"%s\"\n", optarg); 75915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 76015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 76115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 76215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 76315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 'f': 764a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson option.flags_specified = 1; 76515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.flags = strtoul(optarg, &e, 0); 76615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (!*optarg || (e && *e)) { 76715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, 76815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson "Invalid --flags \"%s\"\n", optarg); 76915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 77015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 771a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson break; 77215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 'd': 77315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.loemdir = optarg; 77415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 77515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case 'l': 77615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson option.loemid = optarg; 77715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 778c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson case OPT_FV: 779c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.fv_specified = 1; 780c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson /* fallthrough */ 7815f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_INFILE: /* aka "--vmlinuz" */ 7825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson inout_file_count++; 7835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson infile = optarg; 7845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 7855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_OUTFILE: 7865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson inout_file_count++; 7875f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.outfile = optarg; 7885f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 7895f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_BOOTLOADER: 7905f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.bootloader_data = ReadFile( 7915f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson optarg, &option.bootloader_size); 7925f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!option.bootloader_data) { 7935f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, 7945f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Error reading bootloader file: %s\n", 7955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson strerror(errno)); 7965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 7975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 7985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson Debug("bootloader file size=0x%" PRIx64 "\n", 7995f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.bootloader_size); 8005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 8015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_CONFIG: 8025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.config_data = ReadConfigFile( 8035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson optarg, &option.config_size); 8045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!option.config_data) { 8055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, 8065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Error reading config file: %s\n", 8075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson strerror(errno)); 8085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 8095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 8105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 8115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_ARCH: 8125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* check the first 3 characters to also match x86_64 */ 8135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if ((!strncasecmp(optarg, "x86", 3)) || 8145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson (!strcasecmp(optarg, "amd64"))) 8155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.arch = ARCH_X86; 8165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson else if ((!strcasecmp(optarg, "arm")) || 8175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson (!strcasecmp(optarg, "aarch64"))) 8185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.arch = ARCH_ARM; 8195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson else if (!strcasecmp(optarg, "mips")) 8205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.arch = ARCH_MIPS; 8215f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson else { 8225f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, 8235f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Unknown architecture: \"%s\"\n", 8245f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson optarg); 8255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 8265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 8275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 8285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_KLOADADDR: 8295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.kloadaddr = strtoul(optarg, &e, 0); 8305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!*optarg || (e && *e)) { 8315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, 8325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Invalid --kloadaddr \"%s\"\n", optarg); 8335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 8345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 8355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 8365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_PADDING: 8375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.padding = strtoul(optarg, &e, 0); 8385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!*optarg || (e && *e)) { 8395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, 8405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Invalid --padding \"%s\"\n", optarg); 8415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 8425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 8435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 844c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson case OPT_PEM_SIGNPRIV: 845c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.pem_signpriv = optarg; 846c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson break; 847c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson case OPT_PEM_ALGO: 848c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.pem_algo_specified = 1; 849c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.pem_algo = strtoul(optarg, &e, 0); 850c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if (!*optarg || (e && *e) || 851c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson (option.pem_algo >= kNumAlgorithms)) { 852c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson fprintf(stderr, 853c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "Invalid --pem_algo \"%s\"\n", optarg); 854c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson errorcnt++; 855c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 856c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson break; 857c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson case OPT_PEM_EXTERNAL: 858c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.pem_external = optarg; 859c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson break; 860c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson 86115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case '?': 86215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (optopt) 86315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Unrecognized option: -%c\n", 86415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson optopt); 86515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson else 8665f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Unrecognized option: %s\n", 8675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson argv[optind - 1]); 86815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 86915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 87015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson case ':': 87115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, "Missing argument to -%c\n", optopt); 87215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 87315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 8745f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case 0: /* handled option */ 8755f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 87615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson default: 8775f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson Debug("i=%d\n", i); 87815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson DIE; 87915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 88015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 88115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 8825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* If we don't have an input file already, we need one */ 8835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!infile) { 8845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (argc - optind <= 0) { 8855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 8865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "ERROR: missing input filename\n"); 8875f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson goto done; 8885f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } else { 8895f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson inout_file_count++; 8905f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson infile = argv[optind++]; 8915f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 89215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 89315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 894b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson /* Look for an output file if we don't have one, just in case. */ 895b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson if (!option.outfile && argc - optind > 0) { 896b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson inout_file_count++; 897b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson option.outfile = argv[optind++]; 898b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson } 899b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson 9005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* What are we looking at? */ 9012559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson if (futil_file_type(infile, &type)) { 9022559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson errorcnt++; 9032559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson goto done; 9042559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson } 9055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 9065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* We may be able to infer the type based on the other args */ 9075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (type == FILE_TYPE_UNKNOWN) { 9085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.bootloader_data || option.config_data 9095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson || option.arch != ARCH_UNSPECIFIED) 9105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson type = FILE_TYPE_RAW_KERNEL; 911c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson else if (option.kernel_subkey || option.fv_specified) 912c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson type = FILE_TYPE_RAW_FIRMWARE; 91315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 91415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 9152559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson Debug("type=%s\n", futil_file_type_str(type)); 916b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson 9175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Check the arguments for the type of thing we want to sign */ 9185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson switch (type) { 9195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_UNKNOWN: 92015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson fprintf(stderr, 9215f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Unable to determine the type of the input file\n"); 9225f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 9235f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson goto done; 924c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson case FILE_TYPE_PUBKEY: 925c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.create_new_outfile = 1; 926c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if (option.signprivate && option.pem_signpriv) { 927c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson fprintf(stderr, 928c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson "Only one of --signprivate and --pem_signpriv" 929c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " can be specified\n"); 930c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson errorcnt++; 931c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 932c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if ((option.signprivate && option.pem_algo_specified) || 933c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson (option.pem_signpriv && !option.pem_algo_specified)) { 934c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson fprintf(stderr, "--pem_algo must be used with" 935c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " --pem_signpriv\n"); 936c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson errorcnt++; 937c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 938c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson if (option.pem_external && !option.pem_signpriv) { 939c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson fprintf(stderr, "--pem_external must be used with" 940c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson " --pem_signpriv\n"); 941c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson errorcnt++; 942c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson } 943c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson /* We'll wait to read the PEM file, since the external signer 944c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson * may want to read it instead. */ 945c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson break; 9465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_KEYBLOCK: 9475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Resigning a keyblock is kind of pointless.\n"); 9485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Just create a new one.\n"); 9495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 9505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 9515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_FW_PREAMBLE: 9525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, 9535f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "%s IS a signature. Sign the firmware instead\n", 9545f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson infile); 9555f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 9565f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_GBB: 9575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "There's no way to sign a GBB\n"); 95815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 95915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 9605f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_BIOS_IMAGE: 9615f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_OLD_BIOS_IMAGE: 9625f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.signprivate, "signprivate"); 9635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.keyblock, "keyblock"); 9645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.kernel_subkey, "kernelkey"); 96515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 9665f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_KERN_PREAMBLE: 9675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.signprivate, "signprivate"); 968b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson if (option.vblockonly || inout_file_count > 1) 9695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.create_new_outfile = 1; 9705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 971c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson case FILE_TYPE_RAW_FIRMWARE: 972c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson option.create_new_outfile = 1; 973c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson errorcnt += no_opt_if(!option.signprivate, "signprivate"); 974c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson errorcnt += no_opt_if(!option.keyblock, "keyblock"); 975c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson errorcnt += no_opt_if(!option.kernel_subkey, "kernelkey"); 976c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson errorcnt += no_opt_if(!option.version_specified, "version"); 977c540f59be047d69251b7f9ce0637a8a0c6fe150fBill Richardson break; 9785f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case FILE_TYPE_RAW_KERNEL: 9795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.create_new_outfile = 1; 9805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.signprivate, "signprivate"); 9815f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.keyblock, "keyblock"); 9825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.version_specified, "version"); 9835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.bootloader_data, "bootloader"); 9845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(!option.config_data, "config"); 9855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += no_opt_if(option.arch == ARCH_UNSPECIFIED, "arch"); 98615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson break; 9872559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson case FILE_TYPE_CHROMIUMOS_DISK: 9882559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson fprintf(stderr, "Signing a %s is not yet supported\n", 9892559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson futil_file_type_str(type)); 9902559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson errorcnt++; 9912559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 99215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson default: 9935f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson DIE; 99415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 99515dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 996b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson Debug("infile=%s\n", infile); 997b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson Debug("inout_file_count=%d\n", inout_file_count); 998b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson Debug("option.create_new_outfile=%d\n", option.create_new_outfile); 999b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson 1000b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson /* Make sure we have an output file if one is needed */ 10015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!option.outfile) { 1002b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson if (option.create_new_outfile) { 1003b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson errorcnt++; 1004b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson fprintf(stderr, "Missing output filename\n"); 1005b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson goto done; 10065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } else { 1007b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson option.outfile = infile; 10085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 100915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 101015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 10115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson Debug("option.outfile=%s\n", option.outfile); 10125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 10135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (argc - optind > 0) { 1014b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson errorcnt++; 10155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "ERROR: too many arguments left over\n"); 1016b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson } 1017b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson 10185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (errorcnt) 10195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson goto done; 10205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 102115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson memset(&state, 0, sizeof(state)); 102215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson state.op = FUTIL_OP_SIGN; 102315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 10245f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.create_new_outfile) { 10255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* The input is read-only, the output is write-only. */ 10265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson mapping = MAP_RO; 10275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson state.in_filename = infile; 1028b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson Debug("open RO %s\n", infile); 10295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson ifd = open(infile, O_RDONLY); 10305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (ifd < 0) { 10315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 10325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Can't open %s for reading: %s\n", 10335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson infile, strerror(errno)); 10345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson goto done; 10355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 10365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } else { 10375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* We'll read-modify-write the output file */ 10385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson mapping = MAP_RW; 10395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson state.in_filename = option.outfile; 10405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (inout_file_count > 1) 10415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson futil_copy_file_or_die(infile, option.outfile); 1042b406c1064b3a37002b3d4d953a4932628408f25bBill Richardson Debug("open RW %s\n", option.outfile); 10435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson ifd = open(option.outfile, O_RDWR); 10445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (ifd < 0) { 10455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 10465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Can't open %s for writing: %s\n", 10475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.outfile, strerror(errno)); 10485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson goto done; 10495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 10505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 10515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 10525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (0 != futil_map_file(ifd, mapping, &buf, &buf_len)) { 10535f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 10545f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson goto done; 10555f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 10565f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 10575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += futil_traverse(buf, buf_len, &state, type); 1058b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson 10595f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt += futil_unmap_file(ifd, MAP_RW, buf, buf_len); 106015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 10615f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsondone: 10625f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (ifd >= 0 && close(ifd)) { 106315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt++; 10645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Error when closing ifd: %s\n", 10655f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson strerror(errno)); 106615dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson } 106715dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 106815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (option.signprivate) 106915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson free(option.signprivate); 107015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (option.keyblock) 107115dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson free(option.keyblock); 107215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson if (option.kernel_subkey) 107315dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson free(option.kernel_subkey); 107415dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 10755f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (errorcnt) 10765f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Use --help for usage instructions\n"); 10775f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 107815dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson return !!errorcnt; 107915dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson} 108015dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson 1081779796f57e1e0236ea502248ede2cbea986fca21Bill RichardsonDECLARE_FUTIL_COMMAND(sign, do_sign, 10821eae873b6194db25781233d7a4aaee6a34160eecBill Richardson VBOOT_VERSION_ALL, 10835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Sign / resign various binary components", 1084779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help); 1085