/* SPDX-License-Identifier: GPL-2.0-only */

/*
 * Unlike log.c this implements TPM log according to TPM2.0 specification
 * rather then using coreboot-specific log format.
 *
 * First entry is in TPM1.2 format and serves as a header, the rest are in
 * a newer (agile) format which supports SHA256 and multiple hashes, but we
 * store only one hash.
 *
 * This is defined in "TCG EFI Protocol Specification".
 */

#include <endian.h>
#include <console/console.h>
#include <security/tpm/tspi.h>
#include <security/tpm/tspi/crtm.h>
#include <security/tpm/tspi/logs.h>
#include <region_file.h>
#include <string.h>
#include <symbols.h>
#include <cbmem.h>
#include <vb2_sha.h>

static uint16_t tpmalg_from_vb2_hash(enum vb2_hash_algorithm hash_type)
{
	switch (hash_type) {
	case VB2_HASH_SHA1:
		return TPM2_ALG_SHA1;
	case VB2_HASH_SHA256:
		return TPM2_ALG_SHA256;
	case VB2_HASH_SHA384:
		return TPM2_ALG_SHA384;
	case VB2_HASH_SHA512:
		return TPM2_ALG_SHA512;

	default:
		return 0xFF;
	}
}

void *tpm2_log_cbmem_init(void)
{
	static struct tpm_2_log_table *tclt;
	if (tclt)
		return tclt;

	if (cbmem_possibly_online()) {
		size_t tpm_log_len;
		struct tcg_efi_spec_id_event *hdr;

		tclt = cbmem_find(CBMEM_ID_TPM2_TCG_LOG);
		if (tclt)
			return tclt;

		tpm_log_len = sizeof(struct tpm_2_log_table) +
			MAX_TPM_LOG_ENTRIES * sizeof(struct tpm_2_log_entry);
		tclt = cbmem_add(CBMEM_ID_TPM2_TCG_LOG, tpm_log_len);
		if (!tclt)
			return NULL;

		memset(tclt, 0, tpm_log_len);
		hdr = &tclt->header;

		hdr->event_type = htole32(EV_NO_ACTION);
		hdr->event_size = htole32(33 + sizeof(tclt->vendor));
		strcpy((char *)hdr->signature, TPM_20_SPEC_ID_EVENT_SIGNATURE);
		hdr->platform_class = htole32(0x00); // client platform
		hdr->spec_version_minor = 0x00;
		hdr->spec_version_major = 0x02;
		hdr->spec_errata = 0x00;
		hdr->uintn_size = 0x02; // 64-bit UINT
		hdr->num_of_algorithms = htole32(1);
		hdr->digest_sizes[0].alg_id = htole16(tpmalg_from_vb2_hash(TPM_MEASURE_ALGO));
		hdr->digest_sizes[0].digest_size = htole16(vb2_digest_size(TPM_MEASURE_ALGO));

		tclt->vendor_info_size = sizeof(tclt->vendor);
		tclt->vendor.reserved = 0;
		tclt->vendor.version_major = TPM_20_LOG_VI_MAJOR;
		tclt->vendor.version_minor = TPM_20_LOG_VI_MINOR;
		tclt->vendor.magic = htole32(TPM_20_LOG_VI_MAGIC);
		tclt->vendor.max_entries = htole16(MAX_TPM_LOG_ENTRIES);
		tclt->vendor.num_entries = htole16(0);
		tclt->vendor.entry_size = htole32(sizeof(struct tpm_2_log_entry));
	}

	return tclt;
}

void tpm2_log_dump(void)
{
	int i, j;
	struct tpm_2_log_table *tclt;
	int hash_size;
	const char *alg_name;

	tclt = tpm_log_init();
	if (!tclt)
		return;

	hash_size = vb2_digest_size(TPM_MEASURE_ALGO);
	alg_name = vb2_get_hash_algorithm_name(TPM_MEASURE_ALGO);

	printk(BIOS_INFO, "coreboot TPM 2.0 measurements:\n\n");
	for (i = 0; i < le16toh(tclt->vendor.num_entries); i++) {
		struct tpm_2_log_entry *tce = &tclt->entries[i];

		printk(BIOS_INFO, " PCR-%u ", le32toh(tce->pcr));

		for (j = 0; j < hash_size; j++)
			printk(BIOS_INFO, "%02x", tce->digest[j]);

		printk(BIOS_INFO, " %s [%s]\n", alg_name, tce->data);
	}
	printk(BIOS_INFO, "\n");
}

void tpm2_log_add_table_entry(const char *name, const uint32_t pcr,
			      enum vb2_hash_algorithm digest_algo,
			      const uint8_t *digest,
			      const size_t digest_len)
{
	struct tpm_2_log_table *tclt;
	struct tpm_2_log_entry *tce;

	tclt = tpm_log_init();
	if (!tclt) {
		printk(BIOS_WARNING, "TPM LOG: non-existent!\n");
		return;
	}

	if (!name) {
		printk(BIOS_WARNING, "TPM LOG: entry name not set\n");
		return;
	}

	if (digest_algo != TPM_MEASURE_ALGO) {
		printk(BIOS_WARNING, "TPM LOG: digest is of unsupported type: %s\n",
		       vb2_get_hash_algorithm_name(digest_algo));
		return;
	}

	if (digest_len != vb2_digest_size(TPM_MEASURE_ALGO)) {
		printk(BIOS_WARNING, "TPM LOG: digest has invalid length: %d\n",
		       (int)digest_len);
		return;
	}

	if (le16toh(tclt->vendor.num_entries) >= le16toh(tclt->vendor.max_entries)) {
		printk(BIOS_WARNING, "TPM LOG: log table is full\n");
		return;
	}

	tce = &tclt->entries[le16toh(tclt->vendor.num_entries)];
	tclt->vendor.num_entries = htole16(le16toh(tclt->vendor.num_entries) + 1);

	tce->pcr = htole32(pcr);
	tce->event_type = htole32(EV_ACTION);

	tce->digest_count = htole32(1);
	tce->digest_type = htole16(tpmalg_from_vb2_hash(TPM_MEASURE_ALGO));
	memcpy(tce->digest, digest, vb2_digest_size(TPM_MEASURE_ALGO));

	tce->data_length = htole32(sizeof(tce->data));
	strncpy((char *)tce->data, name, sizeof(tce->data) - 1);
	tce->data[sizeof(tce->data) - 1] = '\0';
}

int tpm2_log_get(int entry_idx, int *pcr, const uint8_t **digest_data,
		 enum vb2_hash_algorithm *digest_algo, const char **event_name)
{
	struct tpm_2_log_table *tclt;
	struct tpm_2_log_entry *tce;

	tclt = tpm_log_init();
	if (!tclt)
		return 1;

	if (entry_idx < 0 || entry_idx >= le16toh(tclt->vendor.num_entries))
		return 1;

	tce = &tclt->entries[entry_idx];

	*pcr = le32toh(tce->pcr);
	*digest_data = tce->digest;
	*digest_algo = TPM_MEASURE_ALGO; /* We validate algorithm on addition */
	*event_name = (char *)tce->data;
	return 0;
}

uint16_t tpm2_log_get_size(const void *log_table)
{
	const struct tpm_2_log_table *tclt = log_table;
	return le16toh(tclt->vendor.num_entries);
}

void tpm2_preram_log_clear(void)
{
	printk(BIOS_INFO, "TPM LOG: clearing the log\n");
	/*
	 * Pre-RAM log is only for internal use and isn't exported anywhere, hence it's header
	 * is not initialized.
	 */
	struct tpm_2_log_table *tclt = (struct tpm_2_log_table *)_tpm_log;
	tclt->vendor.max_entries = htole16(MAX_TPM_LOG_ENTRIES);
	tclt->vendor.num_entries = htole16(0);
}

void tpm2_log_copy_entries(const void *from, void *to)
{
	const struct tpm_2_log_table *from_log = from;
	struct tpm_2_log_table *to_log = to;
	int i;

	for (i = 0; i < le16toh(from_log->vendor.num_entries); i++) {
		struct tpm_2_log_entry *tce =
			&to_log->entries[le16toh(to_log->vendor.num_entries)];
		to_log->vendor.num_entries = htole16(le16toh(to_log->vendor.num_entries) + 1);

		tce->pcr = from_log->entries[i].pcr;
		tce->event_type = from_log->entries[i].event_type;

		tce->digest_count = from_log->entries[i].digest_count;
		tce->digest_type = from_log->entries[i].digest_type;
		memcpy(tce->digest, from_log->entries[i].digest, sizeof(tce->digest));

		tce->data_length = from_log->entries[i].data_length;
		memcpy(tce->data, from_log->entries[i].data, sizeof(tce->data));
	}
}
