blob: a7dbedef4aff1a897fa9026a1b04e4e748b46247 [file] [log] [blame]
/* Copyright (c) 2011 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.
*/
#include <stdio.h>
#include "2sysincludes.h"
#include "2api.h"
#include "2common.h"
#include "2rsa.h"
#include "2sha.h"
#include "host_common.h"
#include "host_key21.h"
#include "host_keyblock.h"
#include "host_key.h"
#include "vb2_common.h"
struct vb2_keyblock *vb2_create_keyblock(
const struct vb2_packed_key *data_key,
const struct vb2_private_key *signing_key,
uint32_t flags)
{
/* Allocate keyblock */
uint32_t signed_size = sizeof(struct vb2_keyblock) + data_key->key_size;
uint32_t sig_data_size =
(signing_key ? vb2_rsa_sig_size(signing_key->sig_alg) : 0);
uint32_t block_size =
signed_size + VB2_SHA512_DIGEST_SIZE + sig_data_size;
struct vb2_keyblock *h = (struct vb2_keyblock *)calloc(block_size, 1);
if (!h)
return NULL;
uint8_t *data_key_dest = (uint8_t *)(h + 1);
uint8_t *block_chk_dest = data_key_dest + data_key->key_size;
uint8_t *block_sig_dest = block_chk_dest + VB2_SHA512_DIGEST_SIZE;
memcpy(h->magic, VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE);
h->header_version_major = VB2_KEYBLOCK_VERSION_MAJOR;
h->header_version_minor = VB2_KEYBLOCK_VERSION_MINOR;
h->keyblock_size = block_size;
h->keyblock_flags = flags;
/* Copy data key */
vb2_init_packed_key(&h->data_key, data_key_dest, data_key->key_size);
vb2_copy_packed_key(&h->data_key, data_key);
/* Set up signature structs so we can calculate the signatures */
vb2_init_signature(&h->keyblock_hash, block_chk_dest,
VB2_SHA512_DIGEST_SIZE, signed_size);
if (signing_key) {
vb2_init_signature(&h->keyblock_signature, block_sig_dest,
sig_data_size, signed_size);
} else {
memset(&h->keyblock_signature, 0,
sizeof(h->keyblock_signature));
}
/* Calculate hash */
struct vb2_signature *chk =
vb2_sha512_signature((uint8_t*)h, signed_size);
vb2_copy_signature(&h->keyblock_hash, chk);
free(chk);
/* Calculate signature */
if (signing_key) {
struct vb2_signature *sigtmp =
vb2_calculate_signature((uint8_t*)h,
signed_size,
signing_key);
vb2_copy_signature(&h->keyblock_signature, sigtmp);
free(sigtmp);
}
/* Return the header */
return h;
}
/* TODO(gauravsh): This could easily be integrated into the function above
* since the code is almost a mirror - I have kept it as such to avoid changing
* the existing interface. */
struct vb2_keyblock *vb2_create_keyblock_external(
const struct vb2_packed_key *data_key,
const char *signing_key_pem_file,
uint32_t algorithm,
uint32_t flags,
const char *external_signer)
{
if (!signing_key_pem_file || !data_key || !external_signer)
return NULL;
uint32_t signed_size = sizeof(struct vb2_keyblock) + data_key->key_size;
uint32_t sig_data_size = vb2_rsa_sig_size(vb2_crypto_to_signature(algorithm));
uint32_t block_size =
signed_size + VB2_SHA512_DIGEST_SIZE + sig_data_size;
/* Allocate keyblock */
struct vb2_keyblock *h = (struct vb2_keyblock *)calloc(block_size, 1);
if (!h)
return NULL;
uint8_t *data_key_dest = (uint8_t *)(h + 1);
uint8_t *block_chk_dest = data_key_dest + data_key->key_size;
uint8_t *block_sig_dest = block_chk_dest + VB2_SHA512_DIGEST_SIZE;
memcpy(h->magic, VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE);
h->header_version_major = VB2_KEYBLOCK_VERSION_MAJOR;
h->header_version_minor = VB2_KEYBLOCK_VERSION_MINOR;
h->keyblock_size = block_size;
h->keyblock_flags = flags;
/* Copy data key */
vb2_init_packed_key(&h->data_key, data_key_dest, data_key->key_size);
vb2_copy_packed_key(&h->data_key, data_key);
/* Set up signature structs so we can calculate the signatures */
vb2_init_signature(&h->keyblock_hash, block_chk_dest,
VB2_SHA512_DIGEST_SIZE, signed_size);
vb2_init_signature(&h->keyblock_signature, block_sig_dest,
sig_data_size, signed_size);
/* Calculate checksum */
struct vb2_signature *chk =
vb2_sha512_signature((uint8_t*)h, signed_size);
vb2_copy_signature(&h->keyblock_hash, chk);
free(chk);
/* Calculate signature */
struct vb2_signature *sigtmp =
vb2_external_signature((uint8_t*)h, signed_size,
signing_key_pem_file, algorithm,
external_signer);
vb2_copy_signature(&h->keyblock_signature, sigtmp);
free(sigtmp);
/* Return the header */
return h;
}
struct vb2_keyblock *vb2_read_keyblock(const char *filename)
{
uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
__attribute__((aligned(VB2_WORKBUF_ALIGN)));
struct vb2_workbuf wb;
vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
struct vb2_keyblock *block;
uint32_t file_size;
if (VB2_SUCCESS !=
vb2_read_file(filename, (uint8_t **)&block, &file_size)) {
fprintf(stderr, "Error reading keyblock file: %s\n", filename);
return NULL;
}
/* Verify the hash of the keyblock, since we can do that without
* the public signing key. */
if (VB2_SUCCESS != vb2_verify_keyblock_hash(block, file_size, &wb)) {
fprintf(stderr, "Invalid keyblock file: %s\n", filename);
free(block);
return NULL;
}
return block;
}
int vb2_write_keyblock(const char *filename,
const struct vb2_keyblock *keyblock)
{
return vb2_write_file(filename, keyblock, keyblock->keyblock_size);
}