162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include "funeth.h"
462306a36Sopenharmony_ci#include "funeth_ktls.h"
562306a36Sopenharmony_ci
662306a36Sopenharmony_cistatic int fun_admin_ktls_create(struct funeth_priv *fp, unsigned int id)
762306a36Sopenharmony_ci{
862306a36Sopenharmony_ci	struct fun_admin_ktls_create_req req = {
962306a36Sopenharmony_ci		.common = FUN_ADMIN_REQ_COMMON_INIT2(FUN_ADMIN_OP_KTLS,
1062306a36Sopenharmony_ci						     sizeof(req)),
1162306a36Sopenharmony_ci		.subop = FUN_ADMIN_SUBOP_CREATE,
1262306a36Sopenharmony_ci		.id = cpu_to_be32(id),
1362306a36Sopenharmony_ci	};
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci	return fun_submit_admin_sync_cmd(fp->fdev, &req.common, NULL, 0, 0);
1662306a36Sopenharmony_ci}
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic int fun_ktls_add(struct net_device *netdev, struct sock *sk,
1962306a36Sopenharmony_ci			enum tls_offload_ctx_dir direction,
2062306a36Sopenharmony_ci			struct tls_crypto_info *crypto_info,
2162306a36Sopenharmony_ci			u32 start_offload_tcp_sn)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	struct funeth_priv *fp = netdev_priv(netdev);
2462306a36Sopenharmony_ci	struct fun_admin_ktls_modify_req req = {
2562306a36Sopenharmony_ci		.common = FUN_ADMIN_REQ_COMMON_INIT2(FUN_ADMIN_OP_KTLS,
2662306a36Sopenharmony_ci						     sizeof(req)),
2762306a36Sopenharmony_ci		.subop = FUN_ADMIN_SUBOP_MODIFY,
2862306a36Sopenharmony_ci		.id = cpu_to_be32(fp->ktls_id),
2962306a36Sopenharmony_ci		.tcp_seq = cpu_to_be32(start_offload_tcp_sn),
3062306a36Sopenharmony_ci	};
3162306a36Sopenharmony_ci	struct fun_admin_ktls_modify_rsp rsp;
3262306a36Sopenharmony_ci	struct fun_ktls_tx_ctx *tx_ctx;
3362306a36Sopenharmony_ci	int rc;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	if (direction != TLS_OFFLOAD_CTX_DIR_TX)
3662306a36Sopenharmony_ci		return -EOPNOTSUPP;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (crypto_info->version == TLS_1_2_VERSION)
3962306a36Sopenharmony_ci		req.version = FUN_KTLS_TLSV2;
4062306a36Sopenharmony_ci	else
4162306a36Sopenharmony_ci		return -EOPNOTSUPP;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	switch (crypto_info->cipher_type) {
4462306a36Sopenharmony_ci	case TLS_CIPHER_AES_GCM_128: {
4562306a36Sopenharmony_ci		struct tls12_crypto_info_aes_gcm_128 *c = (void *)crypto_info;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci		req.cipher = FUN_KTLS_CIPHER_AES_GCM_128;
4862306a36Sopenharmony_ci		memcpy(req.key, c->key, sizeof(c->key));
4962306a36Sopenharmony_ci		memcpy(req.iv, c->iv, sizeof(c->iv));
5062306a36Sopenharmony_ci		memcpy(req.salt, c->salt, sizeof(c->salt));
5162306a36Sopenharmony_ci		memcpy(req.record_seq, c->rec_seq, sizeof(c->rec_seq));
5262306a36Sopenharmony_ci		break;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci	default:
5562306a36Sopenharmony_ci		return -EOPNOTSUPP;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	rc = fun_submit_admin_sync_cmd(fp->fdev, &req.common, &rsp,
5962306a36Sopenharmony_ci				       sizeof(rsp), 0);
6062306a36Sopenharmony_ci	memzero_explicit(&req, sizeof(req));
6162306a36Sopenharmony_ci	if (rc)
6262306a36Sopenharmony_ci		return rc;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	tx_ctx = tls_driver_ctx(sk, direction);
6562306a36Sopenharmony_ci	tx_ctx->tlsid = rsp.tlsid;
6662306a36Sopenharmony_ci	tx_ctx->next_seq = start_offload_tcp_sn;
6762306a36Sopenharmony_ci	atomic64_inc(&fp->tx_tls_add);
6862306a36Sopenharmony_ci	return 0;
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic void fun_ktls_del(struct net_device *netdev,
7262306a36Sopenharmony_ci			 struct tls_context *tls_ctx,
7362306a36Sopenharmony_ci			 enum tls_offload_ctx_dir direction)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	struct funeth_priv *fp = netdev_priv(netdev);
7662306a36Sopenharmony_ci	struct fun_admin_ktls_modify_req req;
7762306a36Sopenharmony_ci	struct fun_ktls_tx_ctx *tx_ctx;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	if (direction != TLS_OFFLOAD_CTX_DIR_TX)
8062306a36Sopenharmony_ci		return;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	tx_ctx = __tls_driver_ctx(tls_ctx, direction);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	req.common = FUN_ADMIN_REQ_COMMON_INIT2(FUN_ADMIN_OP_KTLS,
8562306a36Sopenharmony_ci			offsetof(struct fun_admin_ktls_modify_req, tcp_seq));
8662306a36Sopenharmony_ci	req.subop = FUN_ADMIN_SUBOP_MODIFY;
8762306a36Sopenharmony_ci	req.flags = cpu_to_be16(FUN_KTLS_MODIFY_REMOVE);
8862306a36Sopenharmony_ci	req.id = cpu_to_be32(fp->ktls_id);
8962306a36Sopenharmony_ci	req.tlsid = tx_ctx->tlsid;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	fun_submit_admin_sync_cmd(fp->fdev, &req.common, NULL, 0, 0);
9262306a36Sopenharmony_ci	atomic64_inc(&fp->tx_tls_del);
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic int fun_ktls_resync(struct net_device *netdev, struct sock *sk, u32 seq,
9662306a36Sopenharmony_ci			   u8 *rcd_sn, enum tls_offload_ctx_dir direction)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	struct funeth_priv *fp = netdev_priv(netdev);
9962306a36Sopenharmony_ci	struct fun_admin_ktls_modify_req req;
10062306a36Sopenharmony_ci	struct fun_ktls_tx_ctx *tx_ctx;
10162306a36Sopenharmony_ci	int rc;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	if (direction != TLS_OFFLOAD_CTX_DIR_TX)
10462306a36Sopenharmony_ci		return -EOPNOTSUPP;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	tx_ctx = tls_driver_ctx(sk, direction);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	req.common = FUN_ADMIN_REQ_COMMON_INIT2(FUN_ADMIN_OP_KTLS,
10962306a36Sopenharmony_ci			offsetof(struct fun_admin_ktls_modify_req, key));
11062306a36Sopenharmony_ci	req.subop = FUN_ADMIN_SUBOP_MODIFY;
11162306a36Sopenharmony_ci	req.flags = 0;
11262306a36Sopenharmony_ci	req.id = cpu_to_be32(fp->ktls_id);
11362306a36Sopenharmony_ci	req.tlsid = tx_ctx->tlsid;
11462306a36Sopenharmony_ci	req.tcp_seq = cpu_to_be32(seq);
11562306a36Sopenharmony_ci	req.version = 0;
11662306a36Sopenharmony_ci	req.cipher = 0;
11762306a36Sopenharmony_ci	memcpy(req.record_seq, rcd_sn, sizeof(req.record_seq));
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	atomic64_inc(&fp->tx_tls_resync);
12062306a36Sopenharmony_ci	rc = fun_submit_admin_sync_cmd(fp->fdev, &req.common, NULL, 0, 0);
12162306a36Sopenharmony_ci	if (!rc)
12262306a36Sopenharmony_ci		tx_ctx->next_seq = seq;
12362306a36Sopenharmony_ci	return rc;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic const struct tlsdev_ops fun_ktls_ops = {
12762306a36Sopenharmony_ci	.tls_dev_add = fun_ktls_add,
12862306a36Sopenharmony_ci	.tls_dev_del = fun_ktls_del,
12962306a36Sopenharmony_ci	.tls_dev_resync = fun_ktls_resync,
13062306a36Sopenharmony_ci};
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ciint fun_ktls_init(struct net_device *netdev)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	struct funeth_priv *fp = netdev_priv(netdev);
13562306a36Sopenharmony_ci	int rc;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	rc = fun_admin_ktls_create(fp, netdev->dev_port);
13862306a36Sopenharmony_ci	if (rc)
13962306a36Sopenharmony_ci		return rc;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	fp->ktls_id = netdev->dev_port;
14262306a36Sopenharmony_ci	netdev->tlsdev_ops = &fun_ktls_ops;
14362306a36Sopenharmony_ci	netdev->hw_features |= NETIF_F_HW_TLS_TX;
14462306a36Sopenharmony_ci	netdev->features |= NETIF_F_HW_TLS_TX;
14562306a36Sopenharmony_ci	return 0;
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_civoid fun_ktls_cleanup(struct funeth_priv *fp)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	if (fp->ktls_id == FUN_HCI_ID_INVALID)
15162306a36Sopenharmony_ci		return;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	fun_res_destroy(fp->fdev, FUN_ADMIN_OP_KTLS, 0, fp->ktls_id);
15462306a36Sopenharmony_ci	fp->ktls_id = FUN_HCI_ID_INVALID;
15562306a36Sopenharmony_ci}
156