// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2018 Oracle and/or its affiliates. All rights reserved. */

#include <crypto/aead.h>
#include <linux/debugfs.h>
#include <net/xfrm.h>

#include "netdevsim.h"

#define NSIM_IPSEC_AUTH_BITS	128

static ssize_t nsim_dbg_netdev_ops_read(struct file *filp,
					char __user *buffer,
					size_t count, loff_t *ppos)
{
	struct netdevsim *ns = filp->private_data;
	struct nsim_ipsec *ipsec = &ns->ipsec;
	size_t bufsize;
	char *buf, *p;
	int len;
	int i;

	/* the buffer needed is
	 * (num SAs * 3 lines each * ~60 bytes per line) + one more line
	 */
	bufsize = (ipsec->count * 4 * 60) + 60;
	buf = kzalloc(bufsize, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	p = buf;
	p += snprintf(p, bufsize - (p - buf),
		      "SA count=%u tx=%u\n",
		      ipsec->count, ipsec->tx);

	for (i = 0; i < NSIM_IPSEC_MAX_SA_COUNT; i++) {
		struct nsim_sa *sap = &ipsec->sa[i];

		if (!sap->used)
			continue;

		p += snprintf(p, bufsize - (p - buf),
			      "sa[%i] %cx ipaddr=0x%08x %08x %08x %08x\n",
			      i, (sap->rx ? 'r' : 't'), sap->ipaddr[0],
			      sap->ipaddr[1], sap->ipaddr[2], sap->ipaddr[3]);
		p += snprintf(p, bufsize - (p - buf),
			      "sa[%i]    spi=0x%08x proto=0x%x salt=0x%08x crypt=%d\n",
			      i, be32_to_cpu(sap->xs->id.spi),
			      sap->xs->id.proto, sap->salt, sap->crypt);
		p += snprintf(p, bufsize - (p - buf),
			      "sa[%i]    key=0x%08x %08x %08x %08x\n",
			      i, sap->key[0], sap->key[1],
			      sap->key[2], sap->key[3]);
	}

	len = simple_read_from_buffer(buffer, count, ppos, buf, p - buf);

	kfree(buf);
	return len;
}

static const struct file_operations ipsec_dbg_fops = {
	.owner = THIS_MODULE,
	.open = simple_open,
	.read = nsim_dbg_netdev_ops_read,
};

static int nsim_ipsec_find_empty_idx(struct nsim_ipsec *ipsec)
{
	u32 i;

	if (ipsec->count == NSIM_IPSEC_MAX_SA_COUNT)
		return -ENOSPC;

	/* search sa table */
	for (i = 0; i < NSIM_IPSEC_MAX_SA_COUNT; i++) {
		if (!ipsec->sa[i].used)
			return i;
	}

	return -ENOSPC;
}

static int nsim_ipsec_parse_proto_keys(struct xfrm_state *xs,
				       u32 *mykey, u32 *mysalt)
{
	const char aes_gcm_name[] = "rfc4106(gcm(aes))";
	struct net_device *dev = xs->xso.dev;
	unsigned char *key_data;
	char *alg_name = NULL;
	int key_len;

	if (!xs->aead) {
		netdev_err(dev, "Unsupported IPsec algorithm\n");
		return -EINVAL;
	}

	if (xs->aead->alg_icv_len != NSIM_IPSEC_AUTH_BITS) {
		netdev_err(dev, "IPsec offload requires %d bit authentication\n",
			   NSIM_IPSEC_AUTH_BITS);
		return -EINVAL;
	}

	key_data = &xs->aead->alg_key[0];
	key_len = xs->aead->alg_key_len;
	alg_name = xs->aead->alg_name;

	if (strcmp(alg_name, aes_gcm_name)) {
		netdev_err(dev, "Unsupported IPsec algorithm - please use %s\n",
			   aes_gcm_name);
		return -EINVAL;
	}

	/* 160 accounts for 16 byte key and 4 byte salt */
	if (key_len > NSIM_IPSEC_AUTH_BITS) {
		*mysalt = ((u32 *)key_data)[4];
	} else if (key_len == NSIM_IPSEC_AUTH_BITS) {
		*mysalt = 0;
	} else {
		netdev_err(dev, "IPsec hw offload only supports 128 bit keys with optional 32 bit salt\n");
		return -EINVAL;
	}
	memcpy(mykey, key_data, 16);

	return 0;
}

static int nsim_ipsec_add_sa(struct xfrm_state *xs)
{
	struct nsim_ipsec *ipsec;
	struct net_device *dev;
	struct netdevsim *ns;
	struct nsim_sa sa;
	u16 sa_idx;
	int ret;

	dev = xs->xso.dev;
	ns = netdev_priv(dev);
	ipsec = &ns->ipsec;

	if (xs->id.proto != IPPROTO_ESP && xs->id.proto != IPPROTO_AH) {
		netdev_err(dev, "Unsupported protocol 0x%04x for ipsec offload\n",
			   xs->id.proto);
		return -EINVAL;
	}

	if (xs->calg) {
		netdev_err(dev, "Compression offload not supported\n");
		return -EINVAL;
	}

	/* find the first unused index */
	ret = nsim_ipsec_find_empty_idx(ipsec);
	if (ret < 0) {
		netdev_err(dev, "No space for SA in Rx table!\n");
		return ret;
	}
	sa_idx = (u16)ret;

	memset(&sa, 0, sizeof(sa));
	sa.used = true;
	sa.xs = xs;

	if (sa.xs->id.proto & IPPROTO_ESP)
		sa.crypt = xs->ealg || xs->aead;

	/* get the key and salt */
	ret = nsim_ipsec_parse_proto_keys(xs, sa.key, &sa.salt);
	if (ret) {
		netdev_err(dev, "Failed to get key data for SA table\n");
		return ret;
	}

	if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
		sa.rx = true;

		if (xs->props.family == AF_INET6)
			memcpy(sa.ipaddr, &xs->id.daddr.a6, 16);
		else
			memcpy(&sa.ipaddr[3], &xs->id.daddr.a4, 4);
	}

	/* the preparations worked, so save the info */
	memcpy(&ipsec->sa[sa_idx], &sa, sizeof(sa));

	/* the XFRM stack doesn't like offload_handle == 0,
	 * so add a bitflag in case our array index is 0
	 */
	xs->xso.offload_handle = sa_idx | NSIM_IPSEC_VALID;
	ipsec->count++;

	return 0;
}

static void nsim_ipsec_del_sa(struct xfrm_state *xs)
{
	struct netdevsim *ns = netdev_priv(xs->xso.dev);
	struct nsim_ipsec *ipsec = &ns->ipsec;
	u16 sa_idx;

	sa_idx = xs->xso.offload_handle & ~NSIM_IPSEC_VALID;
	if (!ipsec->sa[sa_idx].used) {
		netdev_err(ns->netdev, "Invalid SA for delete sa_idx=%d\n",
			   sa_idx);
		return;
	}

	memset(&ipsec->sa[sa_idx], 0, sizeof(struct nsim_sa));
	ipsec->count--;
}

static bool nsim_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
{
	struct netdevsim *ns = netdev_priv(xs->xso.dev);
	struct nsim_ipsec *ipsec = &ns->ipsec;

	ipsec->ok++;

	return true;
}

static const struct xfrmdev_ops nsim_xfrmdev_ops = {
	.xdo_dev_state_add	= nsim_ipsec_add_sa,
	.xdo_dev_state_delete	= nsim_ipsec_del_sa,
	.xdo_dev_offload_ok	= nsim_ipsec_offload_ok,
};

bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb)
{
	struct sec_path *sp = skb_sec_path(skb);
	struct nsim_ipsec *ipsec = &ns->ipsec;
	struct xfrm_state *xs;
	struct nsim_sa *tsa;
	u32 sa_idx;

	/* do we even need to check this packet? */
	if (!sp)
		return true;

	if (unlikely(!sp->len)) {
		netdev_err(ns->netdev, "no xfrm state len = %d\n",
			   sp->len);
		return false;
	}

	xs = xfrm_input_state(skb);
	if (unlikely(!xs)) {
		netdev_err(ns->netdev, "no xfrm_input_state() xs = %p\n", xs);
		return false;
	}

	sa_idx = xs->xso.offload_handle & ~NSIM_IPSEC_VALID;
	if (unlikely(sa_idx >= NSIM_IPSEC_MAX_SA_COUNT)) {
		netdev_err(ns->netdev, "bad sa_idx=%d max=%d\n",
			   sa_idx, NSIM_IPSEC_MAX_SA_COUNT);
		return false;
	}

	tsa = &ipsec->sa[sa_idx];
	if (unlikely(!tsa->used)) {
		netdev_err(ns->netdev, "unused sa_idx=%d\n", sa_idx);
		return false;
	}

	if (xs->id.proto != IPPROTO_ESP && xs->id.proto != IPPROTO_AH) {
		netdev_err(ns->netdev, "unexpected proto=%d\n", xs->id.proto);
		return false;
	}

	ipsec->tx++;

	return true;
}

void nsim_ipsec_init(struct netdevsim *ns)
{
	ns->netdev->xfrmdev_ops = &nsim_xfrmdev_ops;

#define NSIM_ESP_FEATURES	(NETIF_F_HW_ESP | \
				 NETIF_F_HW_ESP_TX_CSUM | \
				 NETIF_F_GSO_ESP)

	ns->netdev->features |= NSIM_ESP_FEATURES;
	ns->netdev->hw_enc_features |= NSIM_ESP_FEATURES;

	ns->ipsec.pfile = debugfs_create_file("ipsec", 0400,
					      ns->nsim_dev_port->ddir, ns,
					      &ipsec_dbg_fops);
}

void nsim_ipsec_teardown(struct netdevsim *ns)
{
	struct nsim_ipsec *ipsec = &ns->ipsec;

	if (ipsec->count)
		netdev_err(ns->netdev, "tearing down IPsec offload with %d SAs left\n",
			   ipsec->count);
	debugfs_remove_recursive(ipsec->pfile);
}
