/*
 * Copyright (c) 2017 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#if defined(CONFIG_NET_DEBUG_L2_IEEE802154)
#define SYS_LOG_DOMAIN "net/ieee802154"
#define NET_LOG_ENABLED 1
#endif

#include <crypto/cipher.h>
#include <net/net_core.h>

#include "ieee802154_frame.h"
#include "ieee802154_security.h"

extern const u8_t level_2_tag_size[4];

int ieee802154_security_setup_session(struct ieee802154_security_ctx *sec_ctx,
				      u8_t level, u8_t key_mode,
				      u8_t *key, u8_t key_len)
{
	u8_t tag_size;

	if (level > IEEE802154_SECURITY_LEVEL_ENC_MIC_128 ||
	    key_mode > IEEE802154_KEY_ID_MODE_SRC_8_INDEX) {
		return -EINVAL;
	}

	/* ToDo: supporting other key modes */
	if (level > IEEE802154_SECURITY_LEVEL_NONE &&
	    (key_len > IEEE802154_KEY_MAX_LEN || !key ||
	     key_mode != IEEE802154_KEY_ID_MODE_IMPLICIT)) {
		return -EINVAL;
	}

	if (level >= IEEE802154_SECURITY_LEVEL_ENC) {
		tag_size = level_2_tag_size[level - 4];
	} else {
		tag_size = level_2_tag_size[level];
	}

	sec_ctx->level = level;

	if (level > IEEE802154_SECURITY_LEVEL_NONE) {
		memcpy(sec_ctx->key, key, key_len);
		sec_ctx->key_len = key_len;
		sec_ctx->key_mode = key_mode;

		sec_ctx->enc.key.bit_stream = sec_ctx->key;
		sec_ctx->enc.keylen = sec_ctx->key_len;

		sec_ctx->dec.key.bit_stream = sec_ctx->key;
		sec_ctx->dec.keylen = sec_ctx->key_len;
	}

	sec_ctx->enc.mode_params.ccm_info.tag_len = tag_size;
	sec_ctx->dec.mode_params.ccm_info.tag_len = tag_size;

	return 0;
}

bool ieee802154_decrypt_auth(struct ieee802154_security_ctx *sec_ctx,
			     u8_t *frame,
			     u8_t auth_payload_len,
			     u8_t decrypt_payload_len,
			     u8_t *src_ext_addr,
			     u32_t frame_counter)
{
	struct cipher_aead_pkt apkt;
	struct cipher_pkt pkt;
	u8_t nonce[13];
	int ret;

	if (!sec_ctx || sec_ctx->level == IEEE802154_SECURITY_LEVEL_NONE) {
		return true;
	}

	/* See Section 7.3.2 */
	memcpy(nonce, src_ext_addr, IEEE802154_EXT_ADDR_LENGTH);
	nonce[8] = (u8_t)(frame_counter >> 24);
	nonce[9] = (u8_t)(frame_counter >> 16);
	nonce[10] = (u8_t)(frame_counter >> 8);
	nonce[11] = (u8_t)frame_counter;
	nonce[12] = sec_ctx->level;

	pkt.in_buf = decrypt_payload_len ? frame + auth_payload_len : NULL;
	pkt.in_len = decrypt_payload_len;
	pkt.out_buf = frame;
	pkt.out_buf_max = IEEE802154_MTU - IEEE802154_MFR_LENGTH;

	apkt.ad = frame;
	apkt.ad_len = auth_payload_len;
	apkt.tag = sec_ctx->dec.mode_params.ccm_info.tag_len ?
		frame + auth_payload_len + decrypt_payload_len : NULL;
	apkt.pkt = &pkt;

	ret = cipher_ccm_op(&sec_ctx->dec, &apkt, nonce);
	if (ret) {
		NET_ERR("Cannot decrypt/auth (%i): %p %u/%u - fc %u",
			ret, frame, auth_payload_len, decrypt_payload_len,
			frame_counter);
		return false;
	}

	return true;
}

bool ieee802154_encrypt_auth(struct ieee802154_security_ctx *sec_ctx,
			     u8_t *frame,
			     u8_t auth_payload_len,
			     u8_t encrypt_payload_len,
			     u8_t *src_ext_addr)
{
	struct cipher_aead_pkt apkt;
	struct cipher_pkt pkt;
	u8_t nonce[13];
	int ret;

	if (!sec_ctx || sec_ctx->level == IEEE802154_SECURITY_LEVEL_NONE) {
		return true;
	}

	/* See Section 7.3.2 */
	memcpy(nonce, src_ext_addr, IEEE802154_EXT_ADDR_LENGTH);
	sys_put_be32(sec_ctx->frame_counter, &nonce[8]);
	nonce[12] = sec_ctx->level;

	pkt.in_buf = encrypt_payload_len ? frame + auth_payload_len : NULL;
	pkt.in_len = encrypt_payload_len;
	pkt.out_buf = frame;
	pkt.out_buf_max = IEEE802154_MTU - IEEE802154_MFR_LENGTH;

	apkt.ad = frame;
	apkt.ad_len = auth_payload_len;
	apkt.tag = NULL;
	apkt.pkt = &pkt;

	ret = cipher_ccm_op(&sec_ctx->enc, &apkt, nonce);
	if (ret) {
		NET_ERR("Cannot encrypt/auth (%i): %p %u/%u - fc %u",
			ret, frame, auth_payload_len, encrypt_payload_len,
			sec_ctx->frame_counter);
		return false;
	}

	sec_ctx->frame_counter++;

	return true;
}

int ieee802154_security_init(struct ieee802154_security_ctx *sec_ctx)
{
	struct device *dev;
	int ret;

	memset(&sec_ctx->enc, 0, sizeof(struct cipher_ctx));
	memset(&sec_ctx->dec, 0, sizeof(struct cipher_ctx));

	dev = device_get_binding(
		CONFIG_NET_L2_IEEE802154_SECURITY_CRYPTO_DEV_NAME);
	if (!dev) {
		return -ENODEV;
	}

	sec_ctx->enc.flags = cipher_query_hwcaps(dev);
	sec_ctx->dec.flags = cipher_query_hwcaps(dev);

	sec_ctx->enc.mode_params.ccm_info.nonce_len = 13;
	sec_ctx->dec.mode_params.ccm_info.nonce_len = 13;

	ret = cipher_begin_session(dev, &sec_ctx->enc,
				   CRYPTO_CIPHER_ALGO_AES,
				   CRYPTO_CIPHER_MODE_CCM,
				   CRYPTO_CIPHER_OP_ENCRYPT);
	if (ret) {
		NET_ERR("Could not setup encryption context");

		return ret;
	}

	ret = cipher_begin_session(dev, &sec_ctx->dec,
				   CRYPTO_CIPHER_ALGO_AES,
				   CRYPTO_CIPHER_MODE_CCM,
				   CRYPTO_CIPHER_OP_DECRYPT);
	if (ret) {
		NET_ERR("Could not setup decryption context");
		cipher_free_session(dev, &sec_ctx->enc);

		return ret;
	}

	return 0;
}
