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

/**
 * @file
 * @brief 802.15.4 6LoWPAN authentication and encryption implementation
 */

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_ieee802154_security, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);

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

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

extern const uint8_t level_2_tag_size[4];

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

	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->enc.mode_params.ccm_info.tag_len = tag_size;
	sec_ctx->dec.mode_params.ccm_info.tag_len = tag_size;

	sec_ctx->level = level;

	if (level == IEEE802154_SECURITY_LEVEL_NONE) {
		return 0;
	}

	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;

	ret = cipher_begin_session(sec_ctx->enc.device, &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(sec_ctx->dec.device, &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(sec_ctx->enc.device, &sec_ctx->enc);

		return ret;
	}

	return 0;
}

static void prepare_cipher_aead_pkt(uint8_t *frame, uint8_t level, uint8_t hdr_len,
				    uint8_t payload_len, uint8_t tag_size,
				    struct cipher_aead_pkt *apkt, struct cipher_pkt *pkt)
{
	bool is_encrypted = level >= IEEE802154_SECURITY_LEVEL_ENC;
	bool is_authenticated = level != IEEE802154_SECURITY_LEVEL_NONE &&
				level != IEEE802154_SECURITY_LEVEL_ENC;

	/* See section 7.6.3.4.2 */
	pkt->in_buf = is_encrypted && payload_len ? frame + hdr_len : NULL;
	pkt->in_len = is_encrypted ? payload_len : 0;

	/* See section 7.6.3.4.2 */
	uint8_t out_buf_offset = is_encrypted ? hdr_len : hdr_len + payload_len;
	uint8_t auth_len = is_authenticated ? out_buf_offset : 0;

	/* See section 7.5.8.2.1 i) 1) */
	pkt->out_buf = frame + out_buf_offset;
	pkt->out_buf_max = (is_encrypted ? payload_len : 0) + tag_size;

	apkt->ad = is_authenticated ? frame : NULL;
	apkt->ad_len = auth_len;
	apkt->tag = is_authenticated ? frame + hdr_len + payload_len : NULL;
	apkt->pkt = pkt;
}

bool ieee802154_decrypt_auth(struct ieee802154_security_ctx *sec_ctx, uint8_t *frame,
			     uint8_t hdr_len, uint8_t payload_len, uint8_t tag_size,
			     uint8_t *src_ext_addr, uint32_t frame_counter)
{
	struct cipher_aead_pkt apkt;
	struct cipher_pkt pkt;
	uint8_t nonce[13];
	uint8_t level = sec_ctx->level;
	int ret;

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

	if (level == IEEE802154_SECURITY_LEVEL_ENC) {
		/* See comment in ieee802154_encrypt_auth(). */
		NET_ERR("Encrypt-only operation is not supported.");
		return false;
	}

	/* See section 7.6.3.2 */
	memcpy(nonce, src_ext_addr, IEEE802154_EXT_ADDR_LENGTH);
	sys_put_be32(frame_counter, &nonce[8]);
	nonce[12] = level;

	prepare_cipher_aead_pkt(frame, level, hdr_len, payload_len, tag_size, &apkt, &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, hdr_len,
			payload_len, frame_counter);
		return false;
	}

	return true;
}

bool ieee802154_encrypt_auth(struct ieee802154_security_ctx *sec_ctx, uint8_t *frame,
			     uint8_t hdr_len, uint8_t payload_len, uint8_t tag_size,
			     uint8_t *src_ext_addr)
{
	struct cipher_aead_pkt apkt;
	struct cipher_pkt pkt;
	uint8_t nonce[13];
	uint8_t level = sec_ctx->level;
	int ret;

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

	if (level == IEEE802154_SECURITY_LEVEL_ENC) {
		/* TODO: We currently use CCM rather than CCM* as crypto.h does
		 *       not provide access to CCM* as of now.
		 *       The spec requires CCM* to support encryption-only CCM
		 *       operation, see annex B.1
		 */
		NET_ERR("Encrypt-only operation is not supported.");
		return false;
	}

	/* See section 7.5.8.2.1 f) */
	if (sec_ctx->frame_counter == 0xffffffff) {
		NET_ERR("Max frame counter reached. Update key material to reset the counter.");
		return false;
	}

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

	prepare_cipher_aead_pkt(frame, level, hdr_len, payload_len, tag_size, &apkt, &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, hdr_len,
			payload_len, sec_ctx->frame_counter);
		return false;
	}

	sec_ctx->frame_counter++;

	return true;
}

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

	(void)memset(&sec_ctx->enc, 0, sizeof(struct cipher_ctx));
	(void)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 = crypto_query_hwcaps(dev);
	sec_ctx->dec.flags = crypto_query_hwcaps(dev);

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

	sec_ctx->enc.device = dev;
	sec_ctx->dec.device = dev;

	return 0;
}
