/* 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.
 *
 * Common functions between firmware and kernel verified boot.
 * (Firmware portion)
 */

#include "sysincludes.h"

#include "vboot_api.h"
#include "vboot_common.h"
#include "utility.h"

const char *kVbootErrors[VBOOT_ERROR_MAX] = {
	"Success.",
	"Key block invalid.",
	"Key block signature failed.",
	"Key block hash failed.",
	"Public key invalid.",
	"Preamble invalid.",
	"Preamble signature check failed.",
	"Shared data invalid."
};

uint64_t OffsetOf(const void *base, const void *ptr)
{
	return (uint64_t)(size_t)ptr - (uint64_t)(size_t)base;
}

/* Helper functions to get data pointed to by a public key or signature. */

uint8_t *GetPublicKeyData(VbPublicKey *key)
{
	return (uint8_t *)key + key->key_offset;
}

const uint8_t *GetPublicKeyDataC(const VbPublicKey *key)
{
	return (const uint8_t *)key + key->key_offset;
}

uint8_t *GetSignatureData(VbSignature *sig)
{
	return (uint8_t *)sig + sig->sig_offset;
}

const uint8_t *GetSignatureDataC(const VbSignature *sig)
{
	return (const uint8_t *)sig + sig->sig_offset;
}

/*
 * Helper functions to verify the data pointed to by a subfield is inside
 * the parent data.  Returns 0 if inside, 1 if error.
 */

int VerifyMemberInside(const void *parent, uint64_t parent_size,
                       const void *member, uint64_t member_size,
                       uint64_t member_data_offset,
                       uint64_t member_data_size)
{
	uint64_t end = OffsetOf(parent, member);

	if (end > parent_size)
		return 1;

	if (UINT64_MAX - end < member_size)
		return 1;  /* Detect wraparound in integer math */
	if (end + member_size > parent_size)
		return 1;

	if (UINT64_MAX - end < member_data_offset)
		return 1;
	end += member_data_offset;
	if (end > parent_size)
		return 1;

	if (UINT64_MAX - end < member_data_size)
		return 1;
	if (end + member_data_size > parent_size)
		return 1;

	return 0;
}

int VerifyPublicKeyInside(const void *parent, uint64_t parent_size,
                          const VbPublicKey *key)
{
	return VerifyMemberInside(parent, parent_size,
				  key, sizeof(VbPublicKey),
				  key->key_offset, key->key_size);
}

int VerifySignatureInside(const void *parent, uint64_t parent_size,
                          const VbSignature *sig)
{
	return VerifyMemberInside(parent, parent_size,
				  sig, sizeof(VbSignature),
				  sig->sig_offset, sig->sig_size);
}

void PublicKeyInit(VbPublicKey *key, uint8_t *key_data, uint64_t key_size)
{
	key->key_offset = OffsetOf(key, key_data);
	key->key_size = key_size;
	key->algorithm = kNumAlgorithms; /* Key not present yet */
	key->key_version = 0;
}

int PublicKeyCopy(VbPublicKey *dest, const VbPublicKey *src)
{
	if (dest->key_size < src->key_size)
		return 1;

	dest->key_size = src->key_size;
	dest->algorithm = src->algorithm;
	dest->key_version = src->key_version;
	Memcpy(GetPublicKeyData(dest), GetPublicKeyDataC(src), src->key_size);
	return 0;
}

RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key)
{
	RSAPublicKey *rsa;
	uint64_t key_size;

	if (kNumAlgorithms <= key->algorithm) {
		VBDEBUG(("Invalid algorithm.\n"));
		return NULL;
	}
	if (!RSAProcessedKeySize(key->algorithm, &key_size) ||
	    key_size != key->key_size) {
		VBDEBUG(("Wrong key size for algorithm\n"));
		return NULL;
	}

	rsa = RSAPublicKeyFromBuf(GetPublicKeyDataC(key), key->key_size);
	if (!rsa)
		return NULL;

	rsa->algorithm = (unsigned int)key->algorithm;
	return rsa;
}

int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig,
               const RSAPublicKey *key)
{
	if (sig->sig_size != siglen_map[key->algorithm]) {
		VBDEBUG(("Wrong signature size for algorithm.\n"));
		return 1;
	}
	if (sig->data_size > size) {
		VBDEBUG(("Data buffer smaller than length of signed data.\n"));
		return 1;
	}

	if (!RSAVerifyBinary_f(NULL, key, data, sig->data_size,
			       GetSignatureDataC(sig), key->algorithm))
		return 1;

	return 0;
}

int VerifyDigest(const uint8_t *digest, const VbSignature *sig,
                 const RSAPublicKey *key)
{
	if (sig->sig_size != siglen_map[key->algorithm]) {
		VBDEBUG(("Wrong signature size for algorithm.\n"));
		return 1;
	}

	if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest,
					 GetSignatureDataC(sig),
					 key->algorithm))
		return 1;

	return 0;
}

int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
                   const VbPublicKey *key, int hash_only)
{
	const VbSignature *sig;

	/* Sanity checks before attempting signature of data */
	if(size < sizeof(VbKeyBlockHeader)) {
		VBDEBUG(("Not enough space for key block header.\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (SafeMemcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) {
		VBDEBUG(("Not a valid verified boot key block.\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) {
		VBDEBUG(("Incompatible key block header version.\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (size < block->key_block_size) {
		VBDEBUG(("Not enough data for key block.\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (!hash_only && !key) {
		VBDEBUG(("Missing required public key.\n"));
		return VBOOT_PUBLIC_KEY_INVALID;
	}

	/*
	 * Check signature or hash, depending on the hash_only parameter. Note
	 * that we don't require a key even if the keyblock has a signature,
	 * because the caller may not care if the keyblock itself is signed
	 * (for example, booting a Google-signed kernel in developer mode).
	 */
	if (hash_only) {
		/* Check hash */
		uint8_t *header_checksum = NULL;
		int rv;

		sig = &block->key_block_checksum;

		if (VerifySignatureInside(block, block->key_block_size, sig)) {
			VBDEBUG(("Key block hash off end of block\n"));
			return VBOOT_KEY_BLOCK_INVALID;
		}
		if (sig->sig_size != SHA512_DIGEST_SIZE) {
			VBDEBUG(("Wrong hash size for key block.\n"));
			return VBOOT_KEY_BLOCK_INVALID;
		}

		/* Make sure advertised signature data sizes are sane. */
		if (block->key_block_size < sig->data_size) {
			VBDEBUG(("Signature calculated past end of block\n"));
			return VBOOT_KEY_BLOCK_INVALID;
		}

		VBDEBUG(("Checking key block hash only...\n"));
		header_checksum = DigestBuf((const uint8_t *)block,
					    sig->data_size,
					    SHA512_DIGEST_ALGORITHM);
		rv = SafeMemcmp(header_checksum, GetSignatureDataC(sig),
				SHA512_DIGEST_SIZE);
		VbExFree(header_checksum);
		if (rv) {
			VBDEBUG(("Invalid key block hash.\n"));
			return VBOOT_KEY_BLOCK_HASH;
		}
	} else {
		/* Check signature */
		RSAPublicKey *rsa;
		int rv;

		sig = &block->key_block_signature;

		if (VerifySignatureInside(block, block->key_block_size, sig)) {
			VBDEBUG(("Key block signature off end of block\n"));
			return VBOOT_KEY_BLOCK_INVALID;
		}

		rsa = PublicKeyToRSA(key);
		if (!rsa) {
			VBDEBUG(("Invalid public key\n"));
			return VBOOT_PUBLIC_KEY_INVALID;
		}

		/* Make sure advertised signature data sizes are sane. */
		if (block->key_block_size < sig->data_size) {
			VBDEBUG(("Signature calculated past end of block\n"));
			RSAPublicKeyFree(rsa);
			return VBOOT_KEY_BLOCK_INVALID;
		}

		VBDEBUG(("Checking key block signature...\n"));
		rv = VerifyData((const uint8_t *)block, size, sig, rsa);
		RSAPublicKeyFree(rsa);
		if (rv) {
			VBDEBUG(("Invalid key block signature.\n"));
			return VBOOT_KEY_BLOCK_SIGNATURE;
		}
	}

	/* Verify we signed enough data */
	if (sig->data_size < sizeof(VbKeyBlockHeader)) {
		VBDEBUG(("Didn't sign enough data\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}

	/* Verify data key is inside the block and inside signed data */
	if (VerifyPublicKeyInside(block, block->key_block_size,
				  &block->data_key)) {
		VBDEBUG(("Data key off end of key block\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (VerifyPublicKeyInside(block, sig->data_size, &block->data_key)) {
		VBDEBUG(("Data key off end of signed data\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}

	/* Success */
	return VBOOT_SUCCESS;
}

int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader *preamble,
                           uint64_t size, const RSAPublicKey *key)
{
	const VbSignature *sig = &preamble->preamble_signature;

	/* Sanity checks before attempting signature of data */
	if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_0_SIZE) {
		VBDEBUG(("Not enough data for preamble header 2.0.\n"));
		return VBOOT_PREAMBLE_INVALID;
	}
	if (preamble->header_version_major !=
	    FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) {
		VBDEBUG(("Incompatible firmware preamble header version.\n"));
		return VBOOT_PREAMBLE_INVALID;
	}
	if (size < preamble->preamble_size) {
		VBDEBUG(("Not enough data for preamble.\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	/* Check signature */
	if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
		VBDEBUG(("Preamble signature off end of preamble\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	/* Make sure advertised signature data sizes are sane. */
	if (preamble->preamble_size < sig->data_size) {
		VBDEBUG(("Signature calculated past end of the block\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	if (VerifyData((const uint8_t *)preamble, size, sig, key)) {
		VBDEBUG(("Preamble signature validation failed\n"));
		return VBOOT_PREAMBLE_SIGNATURE;
	}

	/* Verify we signed enough data */
	if (sig->data_size < sizeof(VbFirmwarePreambleHeader)) {
		VBDEBUG(("Didn't sign enough data\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	/* Verify body signature is inside the signed data */
	if (VerifySignatureInside(preamble, sig->data_size,
				  &preamble->body_signature)) {
		VBDEBUG(("Firmware body signature off end of preamble\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	/* Verify kernel subkey is inside the signed data */
	if (VerifyPublicKeyInside(preamble, sig->data_size,
				  &preamble->kernel_subkey)) {
		VBDEBUG(("Kernel subkey off end of preamble\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	/*
	 * If the preamble header version is at least 2.1, verify we have space
	 * for the added fields from 2.1.
	 */
	if (preamble->header_version_minor >= 1) {
		if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_1_SIZE) {
			VBDEBUG(("Not enough data for preamble header 2.1.\n"));
			return VBOOT_PREAMBLE_INVALID;
		}
	}

	/* Success */
	return VBOOT_SUCCESS;
}

uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader *preamble)
{
	if (preamble->header_version_minor < 1) {
		/*
		 * Old structure; return default flags.  (Note that we don't
		 * need to check header_version_major; if that's not 2 then
		 * VerifyFirmwarePreamble() would have already failed.
		 */
		return 0;
	}

	return preamble->flags;
}

int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
                         uint64_t size, const RSAPublicKey *key)
{
	const VbSignature *sig = &preamble->preamble_signature;

	/* Sanity checks before attempting signature of data */
	if(size < sizeof(VbKernelPreambleHeader)) {
		VBDEBUG(("Not enough data for preamble header.\n"));
		return VBOOT_PREAMBLE_INVALID;
	}
	if (preamble->header_version_major !=
	    KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) {
		VBDEBUG(("Incompatible kernel preamble header version.\n"));
		return VBOOT_PREAMBLE_INVALID;
	}
	if (size < preamble->preamble_size) {
		VBDEBUG(("Not enough data for preamble.\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	/* Check signature */
	if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
		VBDEBUG(("Preamble signature off end of preamble\n"));
		return VBOOT_PREAMBLE_INVALID;
	}
	if (VerifyData((const uint8_t *)preamble, size, sig, key)) {
		VBDEBUG(("Preamble signature validation failed\n"));
		return VBOOT_PREAMBLE_SIGNATURE;
	}

	/* Verify we signed enough data */
	if (sig->data_size < sizeof(VbKernelPreambleHeader)) {
		VBDEBUG(("Didn't sign enough data\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	/* Verify body signature is inside the signed data */
	if (VerifySignatureInside(preamble, sig->data_size,
				  &preamble->body_signature)) {
		VBDEBUG(("Kernel body signature off end of preamble\n"));
		return VBOOT_PREAMBLE_INVALID;
	}

	/* Success */
	return VBOOT_SUCCESS;
}

uint64_t VbSharedDataReserve(VbSharedDataHeader *header, uint64_t size)
{
	uint64_t offs = header->data_used;

	VBDEBUG(("VbSharedDataReserve %d bytes at %d\n", (int)size, (int)offs));

	if (!header || size > header->data_size - header->data_used) {
		VBDEBUG(("VbSharedData buffer out of space.\n"));
		return 0;  /* Not initialized, or not enough space left. */
	}
	header->data_used += size;
	return offs;
}

int VbSharedDataSetKernelKey(VbSharedDataHeader *header, const VbPublicKey *src)
{
	VbPublicKey *kdest = &header->kernel_subkey;

	if (!header)
		return VBOOT_SHARED_DATA_INVALID;

	/* Attempt to allocate space for key, if it hasn't been allocated yet */
	if (!header->kernel_subkey_data_offset) {
		header->kernel_subkey_data_offset =
			VbSharedDataReserve(header, src->key_size);
		if (!header->kernel_subkey_data_offset)
			return VBOOT_SHARED_DATA_INVALID;
		header->kernel_subkey_data_size = src->key_size;
	}

	/* Copy the kernel sign key blob into the destination buffer */
	PublicKeyInit(kdest,
		      (uint8_t *)header + header->kernel_subkey_data_offset,
		      header->kernel_subkey_data_size);

	return PublicKeyCopy(kdest, src);
}
