// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
 */

#include <linux/errno.h>
#include <linux/verification.h>

#include "ipe.h"
#include "eval.h"
#include "fs.h"
#include "policy.h"
#include "policy_parser.h"
#include "audit.h"

/* lock for synchronizing writers across ipe policy */
DEFINE_MUTEX(ipe_policy_lock);

/**
 * ver_to_u64() - Convert an internal ipe_policy_version to a u64.
 * @p: Policy to extract the version from.
 *
 * Bits (LSB is index 0):
 *	[48,32] -> Major
 *	[32,16] -> Minor
 *	[16, 0] -> Revision
 *
 * Return: u64 version of the embedded version structure.
 */
static inline u64 ver_to_u64(const struct ipe_policy *const p)
{
	u64 r;

	r = (((u64)p->parsed->version.major) << 32)
	  | (((u64)p->parsed->version.minor) << 16)
	  | ((u64)(p->parsed->version.rev));

	return r;
}

/**
 * ipe_free_policy() - Deallocate a given IPE policy.
 * @p: Supplies the policy to free.
 *
 * Safe to call on IS_ERR/NULL.
 */
void ipe_free_policy(struct ipe_policy *p)
{
	if (IS_ERR_OR_NULL(p))
		return;

	ipe_del_policyfs_node(p);
	ipe_free_parsed_policy(p->parsed);
	/*
	 * p->text is allocated only when p->pkcs7 is not NULL
	 * otherwise it points to the plaintext data inside the pkcs7
	 */
	if (!p->pkcs7)
		kfree(p->text);
	kfree(p->pkcs7);
	kfree(p);
}

static int set_pkcs7_data(void *ctx, const void *data, size_t len,
			  size_t asn1hdrlen __always_unused)
{
	struct ipe_policy *p = ctx;

	p->text = (const char *)data;
	p->textlen = len;

	return 0;
}

/**
 * ipe_update_policy() - parse a new policy and replace old with it.
 * @root: Supplies a pointer to the securityfs inode saved the policy.
 * @text: Supplies a pointer to the plain text policy.
 * @textlen: Supplies the length of @text.
 * @pkcs7: Supplies a pointer to a buffer containing a pkcs7 message.
 * @pkcs7len: Supplies the length of @pkcs7len.
 *
 * @text/@textlen is mutually exclusive with @pkcs7/@pkcs7len - see
 * ipe_new_policy.
 *
 * Context: Requires root->i_rwsem to be held.
 * Return:
 * * %0	- Success
 * * %-ENOENT	- Policy was deleted while updating
 * * %-EINVAL	- Policy name mismatch
 * * %-ESTALE	- Policy version too old
 */
int ipe_update_policy(struct inode *root, const char *text, size_t textlen,
		      const char *pkcs7, size_t pkcs7len)
{
	struct ipe_policy *old, *ap, *new = NULL;
	int rc = 0;

	old = (struct ipe_policy *)root->i_private;
	if (!old)
		return -ENOENT;

	new = ipe_new_policy(text, textlen, pkcs7, pkcs7len);
	if (IS_ERR(new))
		return PTR_ERR(new);

	if (strcmp(new->parsed->name, old->parsed->name)) {
		rc = -EINVAL;
		goto err;
	}

	if (ver_to_u64(old) >= ver_to_u64(new)) {
		rc = -ESTALE;
		goto err;
	}

	root->i_private = new;
	swap(new->policyfs, old->policyfs);
	ipe_audit_policy_load(new);

	mutex_lock(&ipe_policy_lock);
	ap = rcu_dereference_protected(ipe_active_policy,
				       lockdep_is_held(&ipe_policy_lock));
	if (old == ap) {
		rcu_assign_pointer(ipe_active_policy, new);
		mutex_unlock(&ipe_policy_lock);
		ipe_audit_policy_activation(old, new);
	} else {
		mutex_unlock(&ipe_policy_lock);
	}
	synchronize_rcu();
	ipe_free_policy(old);

	return 0;
err:
	ipe_free_policy(new);
	return rc;
}

/**
 * ipe_new_policy() - Allocate and parse an ipe_policy structure.
 *
 * @text: Supplies a pointer to the plain-text policy to parse.
 * @textlen: Supplies the length of @text.
 * @pkcs7: Supplies a pointer to a pkcs7-signed IPE policy.
 * @pkcs7len: Supplies the length of @pkcs7.
 *
 * @text/@textlen Should be NULL/0 if @pkcs7/@pkcs7len is set.
 *
 * Return:
 * * a pointer to the ipe_policy structure	- Success
 * * %-EBADMSG				- Policy is invalid
 * * %-ENOMEM				- Out of memory (OOM)
 * * %-ERANGE				- Policy version number overflow
 * * %-EINVAL				- Policy version parsing error
 * * %-ENOKEY				- Policy signing key not found
 * * %-EKEYREJECTED			- Policy signature verification failed
 */
struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
				  const char *pkcs7, size_t pkcs7len)
{
	struct ipe_policy *new = NULL;
	int rc = 0;

	new = kzalloc_obj(*new);
	if (!new)
		return ERR_PTR(-ENOMEM);

	if (!text) {
		new->pkcs7len = pkcs7len;
		new->pkcs7 = kmemdup(pkcs7, pkcs7len, GFP_KERNEL);
		if (!new->pkcs7) {
			rc = -ENOMEM;
			goto err;
		}

		rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len,
#ifdef CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING
					    VERIFY_USE_SECONDARY_KEYRING,
#else
					    NULL,
#endif
					    VERIFYING_UNSPECIFIED_SIGNATURE,
					    set_pkcs7_data, new);
#ifdef CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING
		if (rc == -ENOKEY || rc == -EKEYREJECTED)
			rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len,
						    VERIFY_USE_PLATFORM_KEYRING,
						    VERIFYING_UNSPECIFIED_SIGNATURE,
						    set_pkcs7_data, new);
#endif
		if (rc)
			goto err;
	} else {
		new->textlen = textlen;
		new->text = kstrdup(text, GFP_KERNEL);
		if (!new->text) {
			rc = -ENOMEM;
			goto err;
		}
	}

	rc = ipe_parse_policy(new);
	if (rc)
		goto err;

	return new;
err:
	ipe_free_policy(new);
	return ERR_PTR(rc);
}

/**
 * ipe_set_active_pol() - Make @p the active policy.
 * @p: Supplies a pointer to the policy to make active.
 *
 * Context: Requires root->i_rwsem, which i_private has the policy, to be held.
 * Return:
 * * %0	- Success
 * * %-EINVAL	- New active policy version is invalid
 */
int ipe_set_active_pol(const struct ipe_policy *p)
{
	struct ipe_policy *ap = NULL;

	mutex_lock(&ipe_policy_lock);

	ap = rcu_dereference_protected(ipe_active_policy,
				       lockdep_is_held(&ipe_policy_lock));
	if (ap == p) {
		mutex_unlock(&ipe_policy_lock);
		return 0;
	}
	if (ap && ver_to_u64(ap) > ver_to_u64(p)) {
		mutex_unlock(&ipe_policy_lock);
		return -EINVAL;
	}

	rcu_assign_pointer(ipe_active_policy, p);
	ipe_audit_policy_activation(ap, p);
	mutex_unlock(&ipe_policy_lock);

	return 0;
}
