/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Misc functions which need access to vb2_context but are not public APIs
 */

#include "2api.h"
#include "2common.h"
#include "2misc.h"
#include "2nvstorage.h"
#include "2rsa.h"
#include "2secdata.h"
#include "2sha.h"
#include "2sysincludes.h"
#include "vb21_common.h"

/**
 * Read an object with a common struct header from a verified boot resource.
 *
 * On success, an object buffer will be allocated in the work buffer, the
 * object will be stored into the buffer, and *buf_ptr will point to the
 * object.
 *
 * @param ctx		Vboot context
 * @param index		Resource index to read
 * @param offset	Byte offset within resource to start at
 * @param buf_ptr	Destination for object pointer
 * @return VB2_SUCCESS, or error code on error.
 */
static vb2_error_t vb21_read_resource_object(struct vb2_context *ctx,
					     enum vb2_resource_index index,
					     uint32_t offset,
					     struct vb2_workbuf *wb,
					     void **buf_ptr)
{
	struct vb21_struct_common c;
	void *buf;
	vb2_error_t rv;

	*buf_ptr = NULL;

	/* Read the common header */
	rv = vb2ex_read_resource(ctx, index, offset, &c, sizeof(c));
	if (rv)
		return rv;

	/* Allocate a buffer for the object, now that we know how big it is */
	buf = vb2_workbuf_alloc(wb, c.total_size);
	if (!buf)
		return VB2_ERROR_READ_RESOURCE_OBJECT_BUF;

	/* Read the object */
	rv = vb2ex_read_resource(ctx, index, offset, buf, c.total_size);
	if (rv) {
		vb2_workbuf_free(wb, c.total_size);
		return rv;
	}

	/* Save the pointer */
	*buf_ptr = buf;
	return VB2_SUCCESS;
}

vb2_error_t vb21_load_fw_keyblock(struct vb2_context *ctx)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
	struct vb2_workbuf wb;

	uint8_t *key_data;
	uint32_t key_size;
	struct vb21_packed_key *packed_key;
	struct vb2_public_key root_key;
	struct vb21_keyblock *kb;

	vb2_error_t rv;

	vb2_workbuf_from_ctx(ctx, &wb);

	/* Read the root key */
	key_size = gbb->rootkey_size;
	key_data = vb2_workbuf_alloc(&wb, key_size);
	if (!key_data)
		return VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY;

	rv = vb2ex_read_resource(ctx, VB2_RES_GBB, gbb->rootkey_offset,
				 key_data, key_size);
	if (rv)
		return rv;

	/* Unpack the root key */
	rv = vb21_unpack_key(&root_key, key_data, key_size);
	if (rv)
		return rv;

	/*
	 * Load the firmware keyblock common header into the work buffer after
	 * the root key.
	 */
	rv = vb21_read_resource_object(ctx, VB2_RES_FW_VBLOCK, 0, &wb,
				       (void **)&kb);
	if (rv)
		return rv;

	/* Verify the keyblock */
	rv = vb21_verify_keyblock(kb, kb->c.total_size, &root_key, &wb);
	if (rv) {
		vb2api_fail(ctx, VB2_RECOVERY_FW_KEYBLOCK, rv);
		return rv;
	}

	/* Preamble follows the keyblock in the vblock */
	sd->vblock_preamble_offset = kb->c.total_size;

	packed_key = (struct vb21_packed_key *)((uint8_t *)kb + kb->key_offset);

	/* Key version is the upper 16 bits of the composite firmware version */
	if (packed_key->key_version > 0xffff)
		rv = VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE;
	if (!rv && packed_key->key_version < (sd->fw_version_secdata >> 16)) {
		if (gbb->flags & VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK)
			VB2_DEBUG("Ignoring FW key rollback due to GBB flag\n");
		else
			rv = VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK;
	}
	if (rv) {
		vb2api_fail(ctx, VB2_RECOVERY_FW_KEY_ROLLBACK, rv);
		return rv;
	}

	sd->fw_version = packed_key->key_version << 16;

	/*
	 * Save the data key in the work buffer.  This overwrites the root key
	 * we read above.  That's ok, because now that we have the data key we
	 * no longer need the root key.
	 *
	 * Use memmove() instead of memcpy().  In theory, the destination will
	 * never overlap with the source because the root key is likely to be
	 * at least as large as the data key, but there's no harm here in being
	 * paranoid.
	 */
	memmove(key_data, packed_key, packed_key->c.total_size);
	packed_key = (struct vb21_packed_key *)key_data;

	/* Save the packed key offset and size */
	sd->data_key_offset = vb2_offset_of(sd, key_data);
	sd->data_key_size = packed_key->c.total_size;

	/* Data key will persist in the workbuf after we return */
	vb2_set_workbuf_used(ctx, sd->data_key_offset + sd->data_key_size);

	return VB2_SUCCESS;
}

vb2_error_t vb21_load_fw_preamble(struct vb2_context *ctx)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
	struct vb2_workbuf wb;

	uint8_t *key_data = vb2_member_of(sd, sd->data_key_offset);
	uint32_t key_size = sd->data_key_size;
	struct vb2_public_key data_key;

	/* Preamble goes in the next unused chunk of work buffer */
	struct vb21_fw_preamble *pre;

	vb2_error_t rv;

	vb2_workbuf_from_ctx(ctx, &wb);

	/* Unpack the firmware data key */
	if (!sd->data_key_size)
		return VB2_ERROR_FW_PREAMBLE2_DATA_KEY;

	rv = vb21_unpack_key(&data_key, key_data, key_size);
	if (rv)
		return rv;

	/* Load the firmware preamble */
	rv = vb21_read_resource_object(ctx, VB2_RES_FW_VBLOCK,
				       sd->vblock_preamble_offset, &wb,
				       (void **)&pre);
	if (rv)
		return rv;

	/* Work buffer now contains the data subkey data and the preamble */

	/* Verify the preamble */
	rv = vb21_verify_fw_preamble(pre, pre->c.total_size, &data_key, &wb);
	if (rv) {
		vb2api_fail(ctx, VB2_RECOVERY_FW_PREAMBLE, rv);
		return rv;
	}

	/* Move the preamble down now that the data key is no longer used */
	memmove(key_data, pre, pre->c.total_size);
	pre = (struct vb21_fw_preamble *)key_data;

	/* Data key is now gone */
	sd->data_key_offset = sd->data_key_size = 0;

	/*
	 * Firmware version is the lower 16 bits of the composite firmware
	 * version.
	 */
	if (pre->fw_version > 0xffff)
		rv = VB2_ERROR_FW_PREAMBLE_VERSION_RANGE;
	/* Combine with the key version from vb2_load_fw_keyblock() */
	sd->fw_version |= pre->fw_version;
	if (!rv && sd->fw_version < sd->fw_version_secdata) {
		if (gbb->flags & VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK)
			VB2_DEBUG("Ignoring FW rollback due to GBB flag\n");
		else
			rv = VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK;
	}
	if (rv) {
		vb2api_fail(ctx, VB2_RECOVERY_FW_ROLLBACK, rv);
		return rv;
	}

	/*
	 * If this is a newer version than in secure storage, and we
	 * successfully booted the same slot last boot, roll forward the
	 * version in secure storage.
	 */
	if (sd->fw_version > sd->fw_version_secdata &&
	    sd->last_fw_slot == sd->fw_slot &&
	    sd->last_fw_result == VB2_FW_RESULT_SUCCESS) {
		sd->fw_version_secdata = sd->fw_version;
		vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS,
					 sd->fw_version);
	}

	/* Keep track of where we put the preamble */
	sd->preamble_offset = vb2_offset_of(sd, pre);
	sd->preamble_size = pre->c.total_size;

	/* Preamble will persist in work buffer after we return */
	vb2_set_workbuf_used(ctx, sd->preamble_offset + sd->preamble_size);

	return VB2_SUCCESS;
}
