/*
 **************************************************************************
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE
 **************************************************************************
 */

/*
 * nss_tlsmgr_crypto.c
 *	NSS TLS Manager crypto object
 */

#include <linux/version.h>
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/tlshdr.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/crypto.h>
#include <linux/debugfs.h>
#include <linux/rtnetlink.h>
#include <net/ipv6.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/atomic.h>

#include <crypto/algapi.h>
#include <crypto/aead.h>
#include <crypto/aes.h>
#include <crypto/authenc.h>
#include <crypto/des.h>
#include <crypto/sha.h>
#include <crypto/skcipher.h>
#include <crypto/hash.h>
#include <crypto/internal/hash.h>

#include <nss_api_if.h>
#include <nss_dynamic_interface.h>

#include <nss_cryptoapi.h>
#include <nss_tls.h>
#include <nss_tlsmgr.h>

#include "nss_tlsmgr_ctx.h"
#include "nss_tlsmgr_crypto.h"
#include "nss_tlsmgr_tun.h"
#include "nss_tlsmgr_priv.h"

#define NSS_TLSMGR_KEY_PARAM_SIZE RTA_SPACE(sizeof(struct crypto_authenc_key_param))

static struct nss_tlsmgr_algo_info tlsmgr_algo_info[NSS_TLSMGR_ALGO_MAX] = {
	{"cipher_null", NSS_TLSMGR_KEY_PARAM_SIZE},
	{"hmac(sha1)", NSS_TLSMGR_KEY_PARAM_SIZE},
	{"hmac(sha256)", NSS_TLSMGR_KEY_PARAM_SIZE},
	{"authenc(hmac(sha1),cbc(aes))", NSS_TLSMGR_KEY_PARAM_SIZE},
	{"authenc(hmac(sha256),cbc(aes))", NSS_TLSMGR_KEY_PARAM_SIZE},
	{"authenc(hmac(sha1),cbc(des3_ede))", NSS_TLSMGR_KEY_PARAM_SIZE},
	{"authenc(hmac(sha256),cbc(des3_ede))", NSS_TLSMGR_KEY_PARAM_SIZE},
};

/*
 * nss_tlsmgr_crypto_free()
 *	Free the Crypto context.
 */
void nss_tlsmgr_crypto_free(struct nss_tlsmgr_crypto *ntc)
{
	if (ntc->aead)
		crypto_free_aead(ntc->aead);

	if (ntc->ahash)
		crypto_free_ahash(ntc->ahash);

	vfree(ntc);
}

/*
 * nss_tlsmgr_crypto_alloc()
 *	Allocate crypto node and configure crypto
 */
struct nss_tlsmgr_crypto *nss_tlsmgr_crypto_alloc(struct nss_tlsmgr_config *cfg)
{
	struct crypto_authenc_key_param *key_param;
	struct nss_tlsmgr_algo_info *info;
	struct nss_tlsmgr_crypto *ntc;
	struct rtattr *rta;
	char *keys, *p;
	uint16_t keylen;

	ntc = vzalloc(sizeof(*ntc));
	if (!ntc) {
		nss_tlsmgr_warn("failed to allocate crypto data\n");
		return NULL;
	}

	INIT_LIST_HEAD(&ntc->list);

	nss_tlsmgr_trace("algo:%d cipher_keylen:%d auth_keylen:%d nonce_len:%d\n",
				cfg->algo, cfg->cipher_key.len, cfg->auth_key.len, cfg->nonce.len);

	info = &tlsmgr_algo_info[cfg->algo];

	switch (cfg->algo) {
	case NSS_TLSMGR_ALGO_AES_CBC_SHA1_HMAC:
	case NSS_TLSMGR_ALGO_AES_CBC_SHA256_HMAC:
	case NSS_TLSMGR_ALGO_3DES_CBC_SHA1_HMAC:
	case NSS_TLSMGR_ALGO_3DES_CBC_SHA256_HMAC:
		ntc->aead = crypto_alloc_aead(info->name, 0, 0);
		if (IS_ERR(ntc->aead)) {
			nss_tlsmgr_warn("failed to allocate crypto aead context for algorithm(%d)\n", cfg->algo);
			vfree(ntc);
			return NULL;
		}

		/*
		 * Construct keys
		 */
		keylen = info->rta_key_sz;
		keylen += cfg->cipher_key.len;
		keylen += cfg->auth_key.len;
		keylen += cfg->nonce.len;

		keys = vzalloc(keylen);
		if (!keys) {
			nss_tlsmgr_warn("failed to allocate key memory\n");
			crypto_free_aead(ntc->aead);
			vfree(ntc);
			return NULL;
		}

		p = keys;
		rta = (void *)p;
		rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
		rta->rta_len = RTA_LENGTH(sizeof(*key_param));
		key_param = RTA_DATA(rta);
		p += RTA_SPACE(sizeof(*key_param));

		/*
		 * Copy authentication key
		 */
		memcpy(p, cfg->auth_key.data, cfg->auth_key.len);
		p += cfg->auth_key.len;

		/*
		 * Copy cipher Key
		 */
		key_param->enckeylen = cpu_to_be32(cfg->cipher_key.len);
		memcpy(p, cfg->cipher_key.data, cfg->cipher_key.len);

		if (crypto_aead_setkey(ntc->aead, keys, keylen)) {
			nss_tlsmgr_warn("failed to configure keys");
			crypto_free_aead(ntc->aead);
			vfree(keys);
			vfree(ntc);
			return NULL;
		}

		nss_cryptoapi_aead_ctx2session(ntc->aead, &ntc->crypto_idx);
		ntc->aead = NULL;
		vfree(keys);
		break;

	case NSS_TLSMGR_ALGO_NULL_SHA1_HMAC:
	case NSS_TLSMGR_ALGO_NULL_SHA256_HMAC:
		ntc->ahash = crypto_alloc_ahash(info->name, 0, 0);
		if (IS_ERR(ntc->ahash)) {
			nss_tlsmgr_warn("%px: failed to allocate crypto ahash context\n", ntc);
			vfree(ntc);
			return NULL;
		}

		if (crypto_ahash_setkey(ntc->ahash, cfg->auth_key.data, cfg->auth_key.len)) {
			nss_tlsmgr_warn("%px: failed to configure keys\n", ntc);
			crypto_free_ahash(ntc->ahash);
			vfree(ntc);
			return NULL;
		}

		nss_cryptoapi_ahash_ctx2session(ntc->ahash, &ntc->crypto_idx);
		ntc->ahash = NULL;
		break;

	default:
		nss_tlsmgr_warn("%px: invalid crypto algorithm(%d)\n", ntc, cfg->algo);
		vfree(ntc);
		return NULL;
	}

	nss_tlsmgr_trace("crypto_aead allocated\n");
	return ntc;
}

/*
 * nss_tlsmgr_crypto_update_null()
 *	Update the NULL crypto keys.
 *
 * This is used to create a dummy crypto session when TLS tunnel is created.
 * This session will be in the active list until user do a crypto update/CCS.
 * Once CCS is triggered by the user, then this dummy session will be removed
 * from the list and this new crypto updates will become the new active session.
 */
nss_tlsmgr_status_t nss_tlsmgr_crypto_update_null(struct net_device *dev, struct nss_tlsmgr_ctx *ctx)
{
        enum nss_tls_msg_type msg_type = NSS_TLS_MSG_TYPE_CIPHER_UPDATE;
	struct nss_tlsmgr_tun *tun = netdev_priv(dev);
	struct nss_tls_cipher_update *ntcu;
	struct nss_tlsmgr_crypto *crypto;
	struct nss_tlsmgr_config cfg;
	struct nss_tls_msg ntm;
	nss_tx_status_t status;

	memset(&cfg, 0, sizeof(struct nss_tlsmgr_config));
	cfg.algo = NSS_TLSMGR_ALGO_NULL_SHA1_HMAC;
	cfg.hdr_ver = TLSHDR_VERSION_1_2;

	/*
	 * Create a dummy crypto session for the first CCS operation
	 */
	crypto = nss_tlsmgr_crypto_alloc(&cfg);
	if (!crypto) {
		nss_tlsmgr_crypto_free(crypto);
		nss_tlsmgr_warn("%px: unable to update encap context data", ctx);
		return NSS_TLSMGR_FAIL_NOMEM;
	}

	memset(&ntm, 0, sizeof(struct nss_tls_msg));

	ntcu = &ntm.msg.cipher_update;
	ntcu->crypto_idx = crypto->crypto_idx;
	ntcu->ver = cfg.hdr_ver;
	ntcu->skip = 1;

	status = nss_tls_tx_msg_sync(ctx->nss_ctx, ctx->ifnum, msg_type, sizeof(*ntcu), &ntm);
	if (status != NSS_TX_SUCCESS) {
		nss_tlsmgr_warn("%px: Failed to configure decap, status:%d, error:%d", ctx, status, ntm.cm.error);
		return false;
	}

	/*
	 * Add crypto to context active list
	 */
	write_lock(&tun->lock);
	list_add_tail(&crypto->list, &ctx->crypto_active);
	write_unlock(&tun->lock);

	nss_tlsmgr_trace("%px: NULL context(0x%x) update done", ctx, ctx->ifnum & ((1 << NSS_CORE_ID_SHIFT) - 1));

	return NSS_TLSMGR_OK;
}

/*
 * nss_tlsmgr_crypto_update_encap()
 *	Update the encapsulation crypto keys.
 */
nss_tlsmgr_status_t nss_tlsmgr_crypto_update_encap(struct net_device *dev, struct nss_tlsmgr_config *cfg)
{
        enum nss_tls_msg_type msg_type = NSS_TLS_MSG_TYPE_CIPHER_UPDATE;
	struct nss_tlsmgr_tun *tun = netdev_priv(dev);
	struct nss_tlsmgr_ctx *ctx = &tun->ctx_enc;
	struct nss_tls_cipher_update *ntcu;
	struct nss_tlsmgr_crypto *crypto;
	struct nss_tls_msg ntm;
	nss_tx_status_t status;

	if ((cfg->hdr_ver != TLSHDR_VERSION_1_1) && (cfg->hdr_ver != TLSHDR_VERSION_1_2)) {
		nss_tlsmgr_warn("%px: Invalid TLS header version: %d", ctx, cfg->hdr_ver);
		return NSS_TLSMGR_FAIL_REC_VERSION;
	}

	if (cfg->algo >= ARRAY_SIZE(tlsmgr_algo_info)) {
		nss_tlsmgr_warn("invalid crypto algorithm\n");
		return -EINVAL;
	}

	crypto = nss_tlsmgr_crypto_alloc(cfg);
	if (!crypto) {
		nss_tlsmgr_warn("%px: unable to update encap context data", ctx);
		return NSS_TLSMGR_FAIL_NOMEM;
	}

	memset(&ntm, 0, sizeof(struct nss_tls_msg));

	ntcu = &ntm.msg.cipher_update;
	ntcu->crypto_idx = crypto->crypto_idx;
	ntcu->ver = cfg->hdr_ver;

	status = nss_tls_tx_msg_sync(ctx->nss_ctx, ctx->ifnum, msg_type, sizeof(*ntcu), &ntm);
	if (status != NSS_TX_SUCCESS) {
		nss_tlsmgr_crypto_free(crypto);
		nss_tlsmgr_warn("%px: Failed to configure encap, status:%d, error:%d", ctx, status, ntm.cm.error);
		return NSS_TLSMGR_FAIL_MESSAGE;
	}

	/*
	 * Add crypto to context active list
	 */
	write_lock(&tun->lock);
	list_add_tail(&crypto->list, &ctx->crypto_active);
	write_unlock(&tun->lock);

	nss_tlsmgr_trace("%px: encap context(0x%x) update done", ctx, ctx->ifnum & ((1 << NSS_CORE_ID_SHIFT) - 1));

	return NSS_TLSMGR_OK;
}
EXPORT_SYMBOL(nss_tlsmgr_crypto_update_encap);

/*
 * nss_tlsmgr_crypto_update_decap()
 *	Update the decapsulation crypto keys.
 */
nss_tlsmgr_status_t nss_tlsmgr_crypto_update_decap(struct net_device *dev, struct nss_tlsmgr_config *cfg)
{
        enum nss_tls_msg_type msg_type = NSS_TLS_MSG_TYPE_CIPHER_UPDATE;
	struct nss_tlsmgr_tun *tun = netdev_priv(dev);
	struct nss_tlsmgr_ctx *ctx = &tun->ctx_dec;
	struct nss_tls_cipher_update *ntcu;
	struct nss_tlsmgr_crypto *crypto;
	struct nss_tls_msg ntm;
	nss_tx_status_t status;

	if ((cfg->hdr_ver != TLSHDR_VERSION_1_1) && (cfg->hdr_ver != TLSHDR_VERSION_1_2)) {
		nss_tlsmgr_warn("%px: Invalid TLS header version: %d", ctx, cfg->hdr_ver);
		return NSS_TLSMGR_FAIL_REC_VERSION;
	}

	if (cfg->algo >= ARRAY_SIZE(tlsmgr_algo_info)) {
		nss_tlsmgr_warn("invalid crypto algorithm\n");
		return -EINVAL;
	}

	crypto = nss_tlsmgr_crypto_alloc(cfg);
	if (!crypto) {
		nss_tlsmgr_warn("%px: unable to update decap context data", ctx);
		return NSS_TLSMGR_FAIL_NOMEM;
	}

	memset(&ntm, 0, sizeof(struct nss_tls_msg));

	ntcu = &ntm.msg.cipher_update;
	ntcu->crypto_idx = crypto->crypto_idx;
	ntcu->ver = cfg->hdr_ver;

	status = nss_tls_tx_msg_sync(ctx->nss_ctx, ctx->ifnum, msg_type, sizeof(*ntcu), &ntm);
	if (status != NSS_TX_SUCCESS) {
		nss_tlsmgr_crypto_free(crypto);
		nss_tlsmgr_warn("%px: Failed to configure decap, status:%d, error:%d", ctx, status, ntm.cm.error);
		return false;
	}

	/*
	 * Add crypto to context active list
	 */
	write_lock(&tun->lock);
	list_add_tail(&crypto->list, &ctx->crypto_active);
	write_unlock(&tun->lock);

	nss_tlsmgr_trace("%px: decap context(0x%x) update done", ctx, ctx->ifnum & ((1 << NSS_CORE_ID_SHIFT) - 1));

	return NSS_TLSMGR_OK;
}
EXPORT_SYMBOL(nss_tlsmgr_crypto_update_decap);
