// SPDX-License-Identifier: GPL-2.0+
/*
 *  Menu-driven UEFI Secure Boot Key Maintenance
 *
 *  Copyright (c) 2022 Masahisa Kojima, Linaro Limited
 */

#include <ansi.h>
#include <charset.h>
#include <console.h>
#include <hexdump.h>
#include <log.h>
#include <malloc.h>
#include <menu.h>
#include <efi_loader.h>
#include <efi_config.h>
#include <efi_variable.h>
#include <crypto/pkcs7_parser.h>

struct eficonfig_sig_data {
	struct efi_signature_list *esl;
	struct efi_signature_data *esd;
	struct list_head list;
	u16 *varname;
};

enum efi_sbkey_signature_type {
	SIG_TYPE_X509 = 0,
	SIG_TYPE_HASH,
	SIG_TYPE_CRL,
	SIG_TYPE_RSA2048,
};

struct eficonfig_sigtype_to_str {
	efi_guid_t sig_type;
	char *str;
	enum efi_sbkey_signature_type type;
};

static const struct eficonfig_sigtype_to_str sigtype_to_str[] = {
	{EFI_CERT_X509_GUID,		"X509",			SIG_TYPE_X509},
	{EFI_CERT_SHA256_GUID,		"SHA256",		SIG_TYPE_HASH},
	{EFI_CERT_X509_SHA256_GUID,	"X509_SHA256 CRL",	SIG_TYPE_CRL},
	{EFI_CERT_X509_SHA384_GUID,	"X509_SHA384 CRL",	SIG_TYPE_CRL},
	{EFI_CERT_X509_SHA512_GUID,	"X509_SHA512 CRL",	SIG_TYPE_CRL},
	/* U-Boot does not support the following signature types */
/*	{EFI_CERT_RSA2048_GUID,		"RSA2048",		SIG_TYPE_RSA2048}, */
/*	{EFI_CERT_RSA2048_SHA256_GUID,	"RSA2048_SHA256",	SIG_TYPE_RSA2048}, */
/*	{EFI_CERT_SHA1_GUID,		"SHA1",			SIG_TYPE_HASH}, */
/*	{EFI_CERT_RSA2048_SHA_GUID,	"RSA2048_SHA",		SIG_TYPE_RSA2048 }, */
/*	{EFI_CERT_SHA224_GUID,		"SHA224",		SIG_TYPE_HASH}, */
/*	{EFI_CERT_SHA384_GUID,		"SHA384",		SIG_TYPE_HASH}, */
/*	{EFI_CERT_SHA512_GUID,		"SHA512",		SIG_TYPE_HASH}, */
};

/**
 * file_have_auth_header() - check file has EFI_VARIABLE_AUTHENTICATION_2 header
 * @buf:	pointer to file
 * @size:	file size
 * Return:	true if file has auth header, false otherwise
 */
static bool file_have_auth_header(void *buf, efi_uintn_t size)
{
	struct efi_variable_authentication_2 *auth = buf;

	if (auth->auth_info.hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
		return false;

	if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
		return false;

	return true;
}

/**
 * file_is_null_key() - check the file is an authenticated and signed null key
 *
 * @auth:	pointer to the file
 * @size:	file size
 * @null_key:	pointer to store the result
 * Return:	status code
 */
static efi_status_t file_is_null_key(struct efi_variable_authentication_2 *auth,
				     efi_uintn_t size, bool *null_key)
{
	efi_uintn_t auth_size =
		sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength;

	if (size < auth_size)
		return EFI_INVALID_PARAMETER;

	*null_key = (size == auth_size);

	return EFI_SUCCESS;
}

/**
 * eficonfig_process_enroll_key() - enroll key into signature database
 *
 * @data:	pointer to the data for each entry
 * Return:	status code
 */
static efi_status_t eficonfig_process_enroll_key(void *data)
{
	u32 attr;
	char *buf = NULL;
	efi_uintn_t size;
	efi_status_t ret;
	bool null_key = false;
	struct efi_file_handle *f = NULL;
	struct efi_device_path *full_dp = NULL;
	struct eficonfig_select_file_info file_info;

	file_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
	if (!file_info.current_path) {
		ret = EFI_OUT_OF_RESOURCES;
		goto out;
	}

	ret = eficonfig_process_select_file(&file_info);
	if (ret != EFI_SUCCESS)
		goto out;

	full_dp = eficonfig_create_device_path(file_info.dp_volume, file_info.current_path);
	if (!full_dp) {
		ret = EFI_OUT_OF_RESOURCES;
		goto out;
	}
	f = efi_file_from_path(full_dp);
	if (!f) {
		ret = EFI_NOT_FOUND;
		goto out;
	}

	size = 0;
	ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, NULL));
	if (ret != EFI_BUFFER_TOO_SMALL)
		goto out;

	buf = malloc(size);
	if (!buf) {
		ret = EFI_OUT_OF_RESOURCES;
		goto out;
	}
	ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, buf));
	if (ret != EFI_SUCCESS)
		goto out;

	size = ((struct efi_file_info *)buf)->file_size;
	free(buf);

	if (!size) {
		eficonfig_print_msg("ERROR! File is empty.");
		ret = EFI_INVALID_PARAMETER;
		goto out;
	}

	buf = malloc(size);
	if (!buf) {
		ret = EFI_OUT_OF_RESOURCES;
		goto out;
	}

	ret = EFI_CALL(f->read(f, &size, buf));
	if (ret != EFI_SUCCESS) {
		eficonfig_print_msg("ERROR! Failed to read file.");
		goto out;
	}
	if (!file_have_auth_header(buf, size)) {
		eficonfig_print_msg("ERROR! Invalid file format. Only .auth variables is allowed.");
		ret = EFI_INVALID_PARAMETER;
		goto out;
	}

	ret = file_is_null_key((struct efi_variable_authentication_2 *)buf,
			       size, &null_key);
	if (ret != EFI_SUCCESS) {
		eficonfig_print_msg("ERROR! Invalid file format.");
		goto out;
	}

	attr = EFI_VARIABLE_NON_VOLATILE |
	       EFI_VARIABLE_BOOTSERVICE_ACCESS |
	       EFI_VARIABLE_RUNTIME_ACCESS |
	       EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;

	/*
	 * PK can enroll only one certificate.
	 * The signed null key is used to clear KEK, db and dbx.
	 * EFI_VARIABLE_APPEND_WRITE attribute must not be set in these cases.
	 */
	if (u16_strcmp(data, u"PK") && !null_key) {
		efi_uintn_t db_size = 0;

		/* check the variable exists. If exists, add APPEND_WRITE attribute */
		ret = efi_get_variable_int(data, efi_auth_var_get_guid(data), NULL,
					   &db_size, NULL,  NULL);
		if (ret == EFI_BUFFER_TOO_SMALL)
			attr |= EFI_VARIABLE_APPEND_WRITE;
	}

	ret = efi_set_variable_int((u16 *)data, efi_auth_var_get_guid((u16 *)data),
				   attr, size, buf, false);
	if (ret != EFI_SUCCESS)
		eficonfig_print_msg("ERROR! Failed to update signature database");

out:
	free(file_info.current_path);
	free(buf);
	efi_free_pool(full_dp);
	if (f)
		EFI_CALL(f->close(f));

	/* return to the parent menu */
	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;

	return ret;
}

/**
 * eficonfig_process_show_siglist() - show signature list content
 *
 * @data:	pointer to the data for each entry
 * Return:	status code
 */
static efi_status_t eficonfig_process_show_siglist(void *data)
{
	u32 i;
	struct eficonfig_sig_data *sg = data;

	puts(ANSI_CURSOR_HIDE);
	puts(ANSI_CLEAR_CONSOLE);
	printf(ANSI_CURSOR_POSITION, 1, 1);

	printf("\n  ** Show Signature Database (%ls) **\n\n"
	       "    Owner GUID:\n"
	       "      %pUL\n",
	       sg->varname, sg->esd->signature_owner.b);

	for (i = 0; i < ARRAY_SIZE(sigtype_to_str); i++) {
		if (!guidcmp(&sg->esl->signature_type, &sigtype_to_str[i].sig_type)) {
			printf("    Signature Type:\n"
			       "      %s\n", sigtype_to_str[i].str);

			switch (sigtype_to_str[i].type) {
			case SIG_TYPE_X509:
			{
				struct x509_certificate *cert_tmp;

				cert_tmp = x509_cert_parse(sg->esd->signature_data,
							   sg->esl->signature_size);
				printf("    Subject:\n"
				       "      %s\n"
				       "    Issuer:\n"
				       "      %s\n",
				       cert_tmp->subject, cert_tmp->issuer);
				break;
			}
			case SIG_TYPE_CRL:
			{
				u32 hash_size = sg->esl->signature_size - sizeof(efi_guid_t) -
						sizeof(struct efi_time);
				struct efi_time *time =
					(struct efi_time *)((u8 *)sg->esd->signature_data +
					hash_size);

				printf("    ToBeSignedHash:\n");
				print_hex_dump("      ", DUMP_PREFIX_NONE, 16, 1,
					       sg->esd->signature_data, hash_size, false);
				printf("    TimeOfRevocation:\n"
				       "      %d-%d-%d %02d:%02d:%02d\n",
				       time->year, time->month, time->day,
				       time->hour, time->minute, time->second);
				break;
			}
			case SIG_TYPE_HASH:
			{
				u32 hash_size = sg->esl->signature_size - sizeof(efi_guid_t);

				printf("    Hash:\n");
				print_hex_dump("      ", DUMP_PREFIX_NONE, 16, 1,
					       sg->esd->signature_data, hash_size, false);
				break;
			}
			default:
				eficonfig_print_msg("ERROR! Unsupported format.");
				return EFI_INVALID_PARAMETER;
			}
		}
	}

	console_flush_stdin();

	printf("\n\n  Press any key to continue");
	getchar();

	return EFI_SUCCESS;
}

/**
 * prepare_signature_list_menu() - create the signature list menu entry
 *
 * @efimenu:	pointer to the efimenu structure
 * @varname:	pointer to the variable name
 * @db:		pointer to the variable raw data
 * @db_size:	variable data size
 * @func:	callback of each entry
 * Return:	status code
 */
static efi_status_t prepare_signature_list_menu(struct efimenu *efi_menu, void *varname,
						void *db, efi_uintn_t db_size,
						eficonfig_entry_func func)
{
	u32 num = 0;
	efi_uintn_t size;
	struct eficonfig_sig_data *sg;
	struct efi_signature_list *esl;
	struct efi_signature_data *esd;
	efi_status_t ret = EFI_SUCCESS;

	INIT_LIST_HEAD(&efi_menu->list);

	esl = db;
	size = db_size;
	while (size > 0) {
		u32 remain;

		esd = (struct efi_signature_data *)((u8 *)esl +
						    (sizeof(struct efi_signature_list) +
						    esl->signature_header_size));
		remain = esl->signature_list_size - sizeof(struct efi_signature_list) -
			 esl->signature_header_size;
		for (; remain > 0; remain -= esl->signature_size) {
			char buf[37];
			char *title;

			if (num >= EFICONFIG_ENTRY_NUM_MAX - 1) {
				ret = EFI_OUT_OF_RESOURCES;
				goto out;
			}

			sg = calloc(1, sizeof(struct eficonfig_sig_data));
			if (!sg) {
				ret = EFI_OUT_OF_RESOURCES;
				goto err;
			}

			snprintf(buf, sizeof(buf), "%pUL", &esd->signature_owner);
			title = strdup(buf);
			if (!title) {
				free(sg);
				ret = EFI_OUT_OF_RESOURCES;
				goto err;
			}

			sg->esl = esl;
			sg->esd = esd;
			sg->varname = varname;
			ret = eficonfig_append_menu_entry(efi_menu, title, func, sg);
			if (ret != EFI_SUCCESS) {
				free(sg);
				free(title);
				goto err;
			}
			esd = (struct efi_signature_data *)((u8 *)esd + esl->signature_size);
			num++;
		}

		size -= esl->signature_list_size;
		esl = (struct efi_signature_list *)((u8 *)esl + esl->signature_list_size);
	}
out:
	ret = eficonfig_append_quit_entry(efi_menu);
err:
	return ret;
}

/**
 * enumerate_and_show_signature_database() - enumerate and show the signature database
 *
 * @data:	pointer to the data for each entry
 * Return:	status code
 */
static efi_status_t enumerate_and_show_signature_database(void *varname)
{
	void *db;
	char buf[50];
	efi_status_t ret;
	efi_uintn_t db_size;
	struct efimenu *efi_menu;
	struct list_head *pos, *n;
	struct eficonfig_entry *entry;

	db = efi_get_var(varname, efi_auth_var_get_guid(varname), &db_size);
	if (!db) {
		eficonfig_print_msg("There is no entry in the signature database.");
		return EFI_NOT_FOUND;
	}

	efi_menu = calloc(1, sizeof(struct efimenu));
	if (!efi_menu) {
		free(db);
		return EFI_OUT_OF_RESOURCES;
	}

	ret = prepare_signature_list_menu(efi_menu, varname, db, db_size,
					  eficonfig_process_show_siglist);
	if (ret != EFI_SUCCESS)
		goto out;

	snprintf(buf, sizeof(buf), "  ** Show Signature Database (%ls) **", (u16 *)varname);
	ret = eficonfig_process_common(efi_menu, buf, eficonfig_menu_desc,
				       eficonfig_display_statusline,
				       eficonfig_print_entry,
				       eficonfig_choice_entry);
out:
	list_for_each_safe(pos, n, &efi_menu->list) {
		entry = list_entry(pos, struct eficonfig_entry, list);
		free(entry->data);
	}
	eficonfig_destroy(efi_menu);
	free(db);

	return ret;
}

/**
 * eficonfig_process_show_signature_database() - process show signature database
 *
 * @data:	pointer to the data for each entry
 * Return:	status code
 */
static efi_status_t eficonfig_process_show_signature_database(void *data)
{
	efi_status_t ret;

	while (1) {
		ret = enumerate_and_show_signature_database(data);
		if (ret != EFI_SUCCESS && ret != EFI_NOT_READY)
			break;
	}

	/* return to the parent menu */
	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;

	return ret;
}

static struct eficonfig_item key_config_menu_items[] = {
	{"Enroll New Key", eficonfig_process_enroll_key},
	{"Show Signature Database", eficonfig_process_show_signature_database},
	{"Quit", eficonfig_process_quit},
};

/**
 * eficonfig_process_set_secure_boot_key() - display the key configuration menu
 *
 * @data:	pointer to the data for each entry
 * Return:	status code
 */
static efi_status_t eficonfig_process_set_secure_boot_key(void *data)
{
	u32 i;
	efi_status_t ret;
	char header_str[32];
	struct efimenu *efi_menu;

	for (i = 0; i < ARRAY_SIZE(key_config_menu_items); i++)
		key_config_menu_items[i].data = data;

	snprintf(header_str, sizeof(header_str), "  ** Configure %ls **", (u16 *)data);

	while (1) {
		efi_menu = eficonfig_create_fixed_menu(key_config_menu_items,
						       ARRAY_SIZE(key_config_menu_items));

		ret = eficonfig_process_common(efi_menu, header_str,
					       eficonfig_menu_desc,
					       eficonfig_display_statusline,
					       eficonfig_print_entry,
					       eficonfig_choice_entry);
		eficonfig_destroy(efi_menu);

		if (ret == EFI_ABORTED)
			break;
	}

	/* return to the parent menu */
	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;

	return ret;
}

static const struct eficonfig_item secure_boot_menu_items[] = {
	{"PK", eficonfig_process_set_secure_boot_key, u"PK"},
	{"KEK", eficonfig_process_set_secure_boot_key, u"KEK"},
	{"db", eficonfig_process_set_secure_boot_key, u"db"},
	{"dbx", eficonfig_process_set_secure_boot_key, u"dbx"},
	{"Quit", eficonfig_process_quit},
};

/**
 * eficonfig_process_secure_boot_config() - display the key list menu
 *
 * @data:	pointer to the data for each entry
 * Return:	status code
 */
efi_status_t eficonfig_process_secure_boot_config(void *data)
{
	efi_status_t ret;
	struct efimenu *efi_menu;

	while (1) {
		char header_str[64];

		snprintf(header_str, sizeof(header_str),
			 "  ** UEFI Secure Boot Key Configuration (SecureBoot : %s) **",
			 (efi_secure_boot_enabled() ? "ON" : "OFF"));

		efi_menu = eficonfig_create_fixed_menu(secure_boot_menu_items,
						       ARRAY_SIZE(secure_boot_menu_items));
		if (!efi_menu) {
			ret = EFI_OUT_OF_RESOURCES;
			break;
		}

		ret = eficonfig_process_common(efi_menu, header_str,
					       eficonfig_menu_desc,
					       eficonfig_display_statusline,
					       eficonfig_print_entry,
					       eficonfig_choice_entry);

		eficonfig_destroy(efi_menu);

		if (ret == EFI_ABORTED)
			break;
	}

	/* return to the parent menu */
	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;

	return ret;
}
