/*
 * Utility functions to work with PROCA certificate
 *
 * Copyright (C) 2018 Samsung Electronics, Inc.
 * Hryhorii Tur, <hryhorii.tur@partner.samsung.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "proca_log.h"
#include "proca_certificate.h"

#include <linux/slab.h>
#include <linux/string.h>
#include <linux/err.h>
#include <crypto/hash.h>
#include <crypto/sha.h>
#include <linux/version.h>
#include <linux/file.h>

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 42)
#include "proca_certificate.asn1.h"
#else
#include "proca_certificate-asn1.h"
#endif

static struct crypto_shash *g_validation_shash;

int proca_certificate_get_flags(void *context, size_t hdrlen,
				unsigned char tag,
				const void *value, size_t vlen)
{
	struct proca_certificate *parsed_cert = context;

	if (!value || !vlen)
		return -EINVAL;

	parsed_cert->flags = *(const uint8_t *)value;

	return 0;
}

int proca_certificate_get_app_name(void *context, size_t hdrlen,
				   unsigned char tag,
				   const void *value, size_t vlen)
{
	struct proca_certificate *parsed_cert = context;

	if (!value || !vlen)
		return -EINVAL;

	parsed_cert->app_name = kmalloc(vlen + 1, GFP_KERNEL);
	if (!parsed_cert->app_name)
		return -ENOMEM;

	memcpy(parsed_cert->app_name, value, vlen);
	parsed_cert->app_name[vlen] = '\0';
	parsed_cert->app_name_size = vlen;

	return 0;
}

int proca_certificate_get_five_signature_hash(void *context, size_t hdrlen,
					      unsigned char tag,
					      const void *value, size_t vlen)
{
	struct proca_certificate *parsed_cert = context;

	if (!value || !vlen)
		return -EINVAL;

	parsed_cert->five_signature_hash = kmalloc(vlen, GFP_KERNEL);
	if (!parsed_cert->five_signature_hash)
		return -ENOMEM;

	memcpy(parsed_cert->five_signature_hash, value, vlen);
	parsed_cert->five_signature_hash_size = vlen;

	return 0;
}

int parse_proca_certificate(const char *certificate_buff,
			    const size_t buff_size,
			    struct proca_certificate *parsed_cert)
{
	int rc = 0;

	memset(parsed_cert, 0, sizeof(*parsed_cert));

	rc = asn1_ber_decoder(&proca_certificate_decoder, parsed_cert,
			      certificate_buff,
			      buff_size);
	if (!parsed_cert->app_name || !parsed_cert->five_signature_hash) {
		PROCA_INFO_LOG("Failed to parse proca certificate.\n");
		deinit_proca_certificate(parsed_cert);
		return -EINVAL;
	}

	return rc;
}

void deinit_proca_certificate(struct proca_certificate *certificate)
{
	kfree(certificate->app_name);
	kfree(certificate->five_signature_hash);
}

int init_certificate_validation_hash(void)
{
	g_validation_shash = crypto_alloc_shash("sha256", 0, 0);
	if (IS_ERR(g_validation_shash)) {
		PROCA_WARN_LOG("can't alloc sha256 alg, rc - %ld.\n",
			PTR_ERR(g_validation_shash));
		return PTR_ERR(g_validation_shash);
	}
	return 0;
}

int compare_with_five_signature(const struct proca_certificate *certificate,
				const void *five_signature,
				const size_t five_signature_size)
{
	SHASH_DESC_ON_STACK(sdesc, g_validation_shash);
	char five_sign_hash[SHA256_DIGEST_SIZE];
	int rc = 0;

	if (sizeof(five_sign_hash) != certificate->five_signature_hash_size) {
		PROCA_DEBUG_LOG(
			"Size of five sign hash is invalid %zu, expected %zu",
			 certificate->five_signature_hash_size,
			 sizeof(five_sign_hash));
		return rc;
	}

	sdesc->tfm = g_validation_shash;
	sdesc->flags = 0;

	rc = crypto_shash_init(sdesc);
	if (rc != 0) {
		PROCA_WARN_LOG("crypto_shash_init failed, rc - %d.\n", rc);
		return 0;
	}

	rc = crypto_shash_digest(sdesc, five_signature,
				 five_signature_size, five_sign_hash);
	if (rc != 0) {
		PROCA_WARN_LOG("crypto_shash_digest failed, rc - %d.\n", rc);
		return 0;
	}

	return !memcmp(five_sign_hash,
		       certificate->five_signature_hash,
		       certificate->five_signature_hash_size);
}

int proca_certificate_copy(struct proca_certificate *dst,
			const struct proca_certificate *src)
{
	BUG_ON(!dst || !src);

	memset(dst, 0, sizeof(*dst));

	if (src->app_name) {
		/*
		 * app_name is NULL-terminated string with len == app_name_size,
		 * so we should duplicate app_name_size + 1 bytes
		 */
		dst->app_name = kmemdup(src->app_name, src->app_name_size + 1,
				GFP_KERNEL);
		dst->app_name_size = src->app_name_size;

		if (unlikely(!dst->app_name))
			return -ENOMEM;
	}

	if (src->five_signature_hash) {
		dst->five_signature_hash = kmemdup(
				src->five_signature_hash,
				src->five_signature_hash_size,
				GFP_KERNEL);
		dst->five_signature_hash_size = src->five_signature_hash_size;

		if (unlikely(!dst->five_signature_hash)) {
			kfree(dst->app_name);
			return -ENOMEM;
		}
	}

	return 0;
}

/* Copied from TA sources */
enum PaFlagBits {
	PaFlagBits_bitAndroid = 0,
	PaFlagBits_bitThirdParty = 1,
	PaFlagBits_bitHmac = 2
};

static bool check_native_pa_id(const struct proca_certificate *parsed_cert,
			       struct task_struct *task)
{
	struct file *exe;
	char *path_buff;
	char *path;
	bool res = false;

	path_buff = kmalloc(parsed_cert->app_name_size + 1, GFP_KERNEL);
	if (!path_buff)
		return false;

	exe = get_task_exe_file(task);
	if (!exe)
		goto path_buff_cleanup;

	path = d_path(&exe->f_path, path_buff, parsed_cert->app_name_size + 1);
	if (IS_ERR(path))
		goto exe_file_cleanup;

	res = !strcmp(path, parsed_cert->app_name);
	if (!res)
		PROCA_WARN_LOG(
			"file path %s and cert app name %s doesn't match\n",
			path, parsed_cert->app_name);

exe_file_cleanup:
	fput(exe);

path_buff_cleanup:
	kfree(path_buff);

	return res;
}

bool is_certificate_relevant_to_task(
			const struct proca_certificate *parsed_cert,
			struct task_struct *task)
{
	const char system_server_app_name[] = "/system/framework/services.jar";
	const char system_server[] = "system_server";
	const size_t max_app_name = 1024;
	char cmdline[max_app_name + 1];
	int cmdline_size;

	if (!(parsed_cert->flags & (1 << PaFlagBits_bitAndroid)))
		if (!check_native_pa_id(parsed_cert, task))
			return false;

	cmdline_size = get_cmdline(task, cmdline, max_app_name);
	cmdline[cmdline_size] = 0;

	// Special case for system_server
	if (!strncmp(parsed_cert->app_name, system_server_app_name,
			parsed_cert->app_name_size)) {
		if (strncmp(cmdline, system_server, sizeof(system_server)))
			return false;
	} else if (parsed_cert->app_name[0] != '/') {
		// Case for Android applications
		PROCA_DEBUG_LOG("Task %d has cmdline : %s\n",
			task->pid, cmdline);
		if (strncmp(cmdline, parsed_cert->app_name,
				parsed_cert->app_name_size))
			return false;
	}

	return true;
}
