/* Copyright (c) 2015 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.
 *
 * Boot descriptor block firmware functions
 */

#include <string.h>
#include "bdb.h"

/*****************************************************************************/

/**
 * Check if string contains a null terminator.
 *
 * Bytes after the null terminator do not need to be null.
 *
 * @param s		String to check
 * @param size		Size of string buffer in characters
 * @return 1 if string has a null terminator, 0 if not
 */
int string_has_null(const char *s, size_t size)
{
	for (; size; size--) {
		if (*s++ == 0)
			return 1;
	}
	return 0;
}

int bdb_check_header(const struct bdb_header *p, size_t size)
{
	if (size < sizeof(*p) || size < p->struct_size)
		return BDB_ERROR_BUF_SIZE;

	if (p->struct_magic != BDB_HEADER_MAGIC)
		return BDB_ERROR_STRUCT_MAGIC;

	if (p->struct_major_version != BDB_HEADER_VERSION_MAJOR)
		return BDB_ERROR_STRUCT_VERSION;

	/* Note that minor version doesn't matter yet */

	if (p->struct_size < sizeof(*p))
		return BDB_ERROR_STRUCT_SIZE;

	if (p->oem_area_0_size & 3)
		return BDB_ERROR_OEM_AREA_SIZE;  /* Not 32-bit aligned */

	/*
	 * Make sure the BDB is at least big enough for us.  At this point, all
	 * the caller may have loaded is this header We'll check if there's
	 * space for everything else after we load it.
	 */
	if (p->bdb_size < sizeof(*p))
		return BDB_ERROR_BDB_SIZE;

	/*
	 * The rest of the fields don't matter yet; we'll check them when we
	 * check the BDB itself.
	 */
	return BDB_SUCCESS;
}

int bdb_check_key(const struct bdb_key *p, size_t size)
{
	size_t expect_key_size = 0;

	if (size < sizeof(*p) || size < p->struct_size)
		return BDB_ERROR_BUF_SIZE;

	if (p->struct_magic != BDB_KEY_MAGIC)
		return BDB_ERROR_STRUCT_MAGIC;

	if (p->struct_major_version != BDB_KEY_VERSION_MAJOR)
		return BDB_ERROR_STRUCT_VERSION;

	/* Note that minor version doesn't matter yet */

	if (!string_has_null(p->description, sizeof(p->description)))
		return BDB_ERROR_DESCRIPTION;

	/* We currently only support SHA-256 */
	if (p->hash_alg != BDB_HASH_ALG_SHA256)
		return BDB_ERROR_HASH_ALG;

	/* Make sure signature algorithm and size are correct */
	switch (p->sig_alg) {
	case BDB_SIG_ALG_RSA4096:
		expect_key_size = BDB_RSA4096_KEY_DATA_SIZE;
		break;
	case BDB_SIG_ALG_ECSDSA521:
		expect_key_size = BDB_ECDSA521_KEY_DATA_SIZE;
		break;
	case BDB_SIG_ALG_RSA3072B:
		expect_key_size = BDB_RSA3072B_KEY_DATA_SIZE;
		break;
	default:
		return BDB_ERROR_SIG_ALG;
	}

	if (p->struct_size < sizeof(*p) + expect_key_size)
		return BDB_ERROR_STRUCT_SIZE;

	return BDB_SUCCESS;
}

int bdb_check_sig(const struct bdb_sig *p, size_t size)
{
	size_t expect_sig_size = 0;

	if (size < sizeof(*p) || size < p->struct_size)
		return BDB_ERROR_BUF_SIZE;

	if (p->struct_magic != BDB_SIG_MAGIC)
		return BDB_ERROR_STRUCT_MAGIC;

	if (p->struct_major_version != BDB_SIG_VERSION_MAJOR)
		return BDB_ERROR_STRUCT_VERSION;

	/* Note that minor version doesn't matter yet */

	if (!string_has_null(p->description, sizeof(p->description)))
		return BDB_ERROR_DESCRIPTION;

	/* We currently only support SHA-256 */
	if (p->hash_alg != BDB_HASH_ALG_SHA256)
		return BDB_ERROR_HASH_ALG;

	/* Make sure signature algorithm and size are correct */
	switch (p->sig_alg) {
	case BDB_SIG_ALG_RSA4096:
		expect_sig_size = BDB_RSA4096_SIG_SIZE;
		break;
	case BDB_SIG_ALG_ECSDSA521:
		expect_sig_size = BDB_ECDSA521_SIG_SIZE;
		break;
	case BDB_SIG_ALG_RSA3072B:
		expect_sig_size = BDB_RSA3072B_SIG_SIZE;
		break;
	default:
		return BDB_ERROR_SIG_ALG;
	}

	if (p->struct_size < sizeof(*p) + expect_sig_size)
		return BDB_ERROR_STRUCT_SIZE;

	return BDB_SUCCESS;
}

int bdb_check_data(const struct bdb_data *p, size_t size)
{
	size_t need_size;

	if (size < sizeof(*p) || size < p->signed_size)
		return BDB_ERROR_BUF_SIZE;

	if (p->struct_magic != BDB_DATA_MAGIC)
		return BDB_ERROR_STRUCT_MAGIC;

	if (p->struct_major_version != BDB_DATA_VERSION_MAJOR)
		return BDB_ERROR_STRUCT_VERSION;

	/* Note that minor version doesn't matter yet */

	if (!string_has_null(p->description, sizeof(p->description)))
		return BDB_ERROR_DESCRIPTION;

	if (p->struct_size < sizeof(*p))
		return BDB_ERROR_STRUCT_SIZE;

	if (p->hash_entry_size < sizeof(struct bdb_hash))
		return BDB_ERROR_HASH_ENTRY_SIZE;

	/* Calculate expected size */
	need_size = p->struct_size + p->num_hashes * p->hash_entry_size;

	/* Make sure OEM area size doesn't cause wraparound */
	if (need_size + p->oem_area_1_size < need_size)
		return BDB_ERROR_OEM_AREA_SIZE;
	if (p->oem_area_1_size & 3)
		return BDB_ERROR_OEM_AREA_SIZE;  /* Not 32-bit aligned */
	need_size += p->oem_area_1_size;

	if (p->signed_size < need_size)
		return BDB_ERROR_SIGNED_SIZE;

	return BDB_SUCCESS;
}

/*****************************************************************************/

const struct bdb_header *bdb_get_header(const void *buf)
{
	return buf;
}

const struct bdb_key *bdb_get_bdbkey(const void *buf)
{
	const struct bdb_header *h = bdb_get_header(buf);
	const uint8_t *b8 = buf;

	/* BDB key follows header */
	return (const struct bdb_key *)(b8 + h->struct_size);
}

const void *bdb_get_oem_area_0(const void *buf)
{
	const struct bdb_key *k = bdb_get_bdbkey(buf);
	const uint8_t *b8 = (const uint8_t *)k;

	/* OEM area 0 follows BDB key */
	return b8 + k->struct_size;
}

const struct bdb_key *bdb_get_subkey(const void *buf)
{
	const struct bdb_header *h = bdb_get_header(buf);
	const uint8_t *b8 = bdb_get_oem_area_0(buf);

	/* Subkey follows OEM area 0 */
	return (const struct bdb_key *)(b8 + h->oem_area_0_size);
}

const struct bdb_sig *bdb_get_header_sig(const void *buf)
{
	const struct bdb_header *h = bdb_get_header(buf);
	const uint8_t *b8 = bdb_get_oem_area_0(buf);

	/* Header signature starts after signed data */
	return (const struct bdb_sig *)(b8 + h->signed_size);
}

const struct bdb_data *bdb_get_data(const void *buf)
{
	const struct bdb_sig *s = bdb_get_header_sig(buf);
	const uint8_t *b8 = (const uint8_t *)s;

	/* Data follows header signature */
	return (const struct bdb_data *)(b8 + s->struct_size);
}

const void *bdb_get_oem_area_1(const void *buf)
{
	const struct bdb_data *p = bdb_get_data(buf);
	const uint8_t *b8 = (const uint8_t *)p;

	/* OEM area 1 follows BDB data */
	return b8 + p->struct_size;
}

const struct bdb_hash *bdb_get_hash(const void *buf, enum bdb_data_type type)
{
	const struct bdb_data *data = bdb_get_data(buf);
	const uint8_t *b8 = bdb_get_oem_area_1(buf);
	int i;

	/* Hashes follow OEM area 0 */
	b8 += data->oem_area_1_size;

	/* Search for a matching hash */
	for (i = 0; i < data->num_hashes; i++, b8 += data->hash_entry_size) {
		const struct bdb_hash *h = (const struct bdb_hash *)b8;

		if (h->type == type)
			return h;
	}

	return NULL;
}

const struct bdb_sig *bdb_get_data_sig(const void *buf)
{
	const struct bdb_data *data = bdb_get_data(buf);
	const uint8_t *b8 = (const uint8_t *)data;

	/* Data signature starts after signed data */
	return (const struct bdb_sig *)(b8 + data->signed_size);
}

/*****************************************************************************/

int bdb_verify_sig(const struct bdb_key *key,
		   const struct bdb_sig *sig,
		   const uint8_t *digest)
{
	/* Key and signature algorithms must match */
	if (key->sig_alg != sig->sig_alg)
		return BDB_ERROR_SIG_ALG;

	switch (key->sig_alg) {
	case BDB_SIG_ALG_RSA4096:
		if (bdb_rsa4096_verify(key->key_data, sig->sig_data, digest))
			return BDB_ERROR_VERIFY_SIG;
		break;
	case BDB_SIG_ALG_ECSDSA521:
		if (bdb_ecdsa521_verify(key->key_data, sig->sig_data, digest))
			return BDB_ERROR_VERIFY_SIG;
		break;
	case BDB_SIG_ALG_RSA3072B:
		if (bdb_rsa3072b_verify(key->key_data, sig->sig_data, digest))
			return BDB_ERROR_VERIFY_SIG;
		break;
	default:
		return BDB_ERROR_VERIFY_SIG;
	}

	return BDB_SUCCESS;
}

int bdb_verify(const void *buf, size_t size, const uint8_t *bdb_key_digest)
{
	const uint8_t *end = (const uint8_t *)buf + size;
	const struct bdb_header *h;
	const struct bdb_key *bdbkey, *subkey;
	const struct bdb_sig *sig;
	const struct bdb_data *data;
	const void *oem;
	uint8_t digest[BDB_SHA256_DIGEST_SIZE];
	int bdb_digest_mismatch;

	/* Make sure buffer doesn't wrap around address space */
	if (end < (const uint8_t *)buf)
		return BDB_ERROR_BUF_SIZE;

	/*
	 * Check header now that we've actually loaded it.  We can't guarantee
	 * this is the same header which was checked before.
	 */
	h = bdb_get_header(buf);
	if (bdb_check_header(h, size))
		return BDB_ERROR_HEADER;

	/* Sanity-check BDB key */
	bdbkey = bdb_get_bdbkey(buf);
	if (bdb_check_key(bdbkey, end - (const uint8_t *)bdbkey))
		return BDB_ERROR_BDBKEY;

	/* Calculate BDB key digest and compare with expected */
	if (bdb_sha256(digest, bdbkey, bdbkey->struct_size))
		return BDB_ERROR_DIGEST;

	bdb_digest_mismatch = memcmp(digest, bdb_key_digest, sizeof(digest));

	/* Make sure OEM area 0 fits */
	oem = bdb_get_oem_area_0(buf);
	if (h->oem_area_0_size > end - (const uint8_t *)oem)
		return BDB_ERROR_OEM_AREA_0;

	/* Sanity-check subkey */
	subkey = bdb_get_subkey(buf);
	if (bdb_check_key(subkey, end - (const uint8_t *)subkey))
		return BDB_ERROR_SUBKEY;

	/* Make sure enough data was signed, and the signed data fits */
	if (h->oem_area_0_size + subkey->struct_size > h->signed_size ||
	    h->signed_size > end - (const uint8_t *)oem)
		return BDB_ERROR_BDB_SIGNED_SIZE;

	/* Sanity-check header signature */
	sig = bdb_get_header_sig(buf);
	if (bdb_check_sig(sig, end - (const uint8_t *)sig))
		return BDB_ERROR_HEADER_SIG;

	/* Make sure it signed the right amount of data */
	if (sig->signed_size != h->signed_size)
		return BDB_ERROR_HEADER_SIG;

	/* Calculate header digest and compare with expected signature */
	if (bdb_sha256(digest, oem, h->signed_size))
		return BDB_ERROR_DIGEST;
	if (bdb_verify_sig(bdbkey, sig, digest))
		return BDB_ERROR_HEADER_SIG;

	/*
	 * Sanity-check data struct.  This also checks that OEM area 1 and the
	 * hashes fit in the remaining buffer.
	 */
	data = bdb_get_data(buf);
	if (bdb_check_data(data, end - (const uint8_t *)data))
		return BDB_ERROR_DATA;

	/* Sanity-check data signature */
	sig = bdb_get_data_sig(buf);
	if (bdb_check_sig(sig, end - (const uint8_t *)sig))
		return BDB_ERROR_DATA_SIG;
	if (sig->signed_size != data->signed_size)
		return BDB_ERROR_DATA_SIG;

	/* Calculate data digest and compare with expected signature */
	if (bdb_sha256(digest, data, data->signed_size))
		return BDB_ERROR_DIGEST;
	if (bdb_verify_sig(subkey, sig, digest))
		return BDB_ERROR_DATA_SIG;

	/* Return success or success-other-than-BDB-key-mismatch */
	return bdb_digest_mismatch ? BDB_GOOD_OTHER_THAN_KEY : BDB_SUCCESS;
}
