Files
OpenCellular/host/lib/host_common.c
Shelley Chen f1f53b3732 vboot: Add flag to vbutil_kernel for reconstruction of vmlinuz image
Adding functionality to allow for rebuilding of vmlinuz after it
has been processed into vblock and header stripped.  Basically appends
the 16-bit header of a vmlinuz image onto the end of the vblock.
BUG=chromium:438302
BRANCH=none
TEST=Successfully ran "make runalltests".
     Also, ran:
     1. Repack kernel block (so that 16-bit header is included):
        "vbutil_kernel --pack kern_0 ..."
     2. Verify kernel: "vbutil_kernel --verify kern_0 ... ".  This should
        be done before booting into kernel, but not necessary for it to work.
     3. Rebuild vmlinuz image:
        "vbutil_kernel --get-vmlinuz kern_0 --vmlinuz-out vm.out"
     4. Set up kexec with vmlinuz (this should complete with no errors):
        "kexec -l vm.out (other kernel cmd line args)"
     5. Boot into kernel:
        "kexec -e"

Change-Id: Iaa1582a1aedf70b43cdb3a56cde1fb248f1793d4
Signed-off-by: Shelley Chen <shchen@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/232750
Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
2015-01-23 21:32:12 +00:00

132 lines
4.0 KiB
C

/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Host functions for verified boot.
*
* TODO: change all 'return 0', 'return 1' into meaningful return codes.
*/
#include <string.h>
#include "host_common.h"
#include "cryptolib.h"
#include "utility.h"
#include "vboot_common.h"
VbFirmwarePreambleHeader *CreateFirmwarePreamble(
uint64_t firmware_version,
const VbPublicKey *kernel_subkey,
const VbSignature *body_signature,
const VbPrivateKey *signing_key,
uint32_t flags)
{
VbFirmwarePreambleHeader *h;
uint64_t signed_size = (sizeof(VbFirmwarePreambleHeader) +
kernel_subkey->key_size +
body_signature->sig_size);
uint64_t block_size = signed_size + siglen_map[signing_key->algorithm];
uint8_t *kernel_subkey_dest;
uint8_t *body_sig_dest;
uint8_t *block_sig_dest;
VbSignature *sigtmp;
/* Allocate key block */
h = (VbFirmwarePreambleHeader *)malloc(block_size);
if (!h)
return NULL;
Memset(h, 0, block_size);
kernel_subkey_dest = (uint8_t *)(h + 1);
body_sig_dest = kernel_subkey_dest + kernel_subkey->key_size;
block_sig_dest = body_sig_dest + body_signature->sig_size;
h->header_version_major = FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR;
h->header_version_minor = FIRMWARE_PREAMBLE_HEADER_VERSION_MINOR;
h->preamble_size = block_size;
h->firmware_version = firmware_version;
h->flags = flags;
/* Copy data key */
PublicKeyInit(&h->kernel_subkey, kernel_subkey_dest,
kernel_subkey->key_size);
PublicKeyCopy(&h->kernel_subkey, kernel_subkey);
/* Copy body signature */
SignatureInit(&h->body_signature, body_sig_dest,
body_signature->sig_size, 0);
SignatureCopy(&h->body_signature, body_signature);
/* Set up signature struct so we can calculate the signature */
SignatureInit(&h->preamble_signature, block_sig_dest,
siglen_map[signing_key->algorithm], signed_size);
/* Calculate signature */
sigtmp = CalculateSignature((uint8_t *)h, signed_size, signing_key);
SignatureCopy(&h->preamble_signature, sigtmp);
free(sigtmp);
/* Return the header */
return h;
}
VbKernelPreambleHeader *CreateKernelPreamble(
uint64_t kernel_version,
uint64_t body_load_address,
uint64_t bootloader_address,
uint64_t bootloader_size,
const VbSignature *body_signature,
uint64_t vmlinuz_header_address,
uint64_t vmlinuz_header_size,
uint64_t desired_size,
const VbPrivateKey *signing_key)
{
VbKernelPreambleHeader *h;
uint64_t signed_size = (sizeof(VbKernelPreambleHeader) +
body_signature->sig_size);
uint64_t block_size = signed_size + siglen_map[signing_key->algorithm];
uint8_t *body_sig_dest;
uint8_t *block_sig_dest;
VbSignature *sigtmp;
/* If the block size is smaller than the desired size, pad it */
if (block_size < desired_size)
block_size = desired_size;
/* Allocate key block */
h = (VbKernelPreambleHeader *)malloc(block_size);
if (!h)
return NULL;
Memset(h, 0, block_size);
body_sig_dest = (uint8_t *)(h + 1);
block_sig_dest = body_sig_dest + body_signature->sig_size;
h->header_version_major = KERNEL_PREAMBLE_HEADER_VERSION_MAJOR;
h->header_version_minor = KERNEL_PREAMBLE_HEADER_VERSION_MINOR;
h->preamble_size = block_size;
h->kernel_version = kernel_version;
h->body_load_address = body_load_address;
h->bootloader_address = bootloader_address;
h->bootloader_size = bootloader_size;
h->vmlinuz_header_address = vmlinuz_header_address;
h->vmlinuz_header_size = vmlinuz_header_size;
/* Copy body signature */
SignatureInit(&h->body_signature, body_sig_dest,
body_signature->sig_size, 0);
SignatureCopy(&h->body_signature, body_signature);
/* Set up signature struct so we can calculate the signature */
SignatureInit(&h->preamble_signature, block_sig_dest,
siglen_map[signing_key->algorithm], signed_size);
/* Calculate signature */
sigtmp = CalculateSignature((uint8_t *)h, signed_size, signing_key);
SignatureCopy(&h->preamble_signature, sigtmp);
free(sigtmp);
/* Return the header */
return h;
}