xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/netronome/nfp/crypto/tls.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*4882a593Smuzhiyun /* Copyright (C) 2019 Netronome Systems, Inc. */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/bitfield.h>
5*4882a593Smuzhiyun #include <linux/ipv6.h>
6*4882a593Smuzhiyun #include <linux/skbuff.h>
7*4882a593Smuzhiyun #include <linux/string.h>
8*4882a593Smuzhiyun #include <net/inet6_hashtables.h>
9*4882a593Smuzhiyun #include <net/tls.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "../ccm.h"
12*4882a593Smuzhiyun #include "../nfp_net.h"
13*4882a593Smuzhiyun #include "crypto.h"
14*4882a593Smuzhiyun #include "fw.h"
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define NFP_NET_TLS_CCM_MBOX_OPS_MASK		\
17*4882a593Smuzhiyun 	(BIT(NFP_CCM_TYPE_CRYPTO_RESET) |	\
18*4882a593Smuzhiyun 	 BIT(NFP_CCM_TYPE_CRYPTO_ADD) |		\
19*4882a593Smuzhiyun 	 BIT(NFP_CCM_TYPE_CRYPTO_DEL) |		\
20*4882a593Smuzhiyun 	 BIT(NFP_CCM_TYPE_CRYPTO_UPDATE))
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define NFP_NET_TLS_OPCODE_MASK_RX			\
23*4882a593Smuzhiyun 	BIT(NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC)
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define NFP_NET_TLS_OPCODE_MASK_TX			\
26*4882a593Smuzhiyun 	BIT(NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC)
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define NFP_NET_TLS_OPCODE_MASK						\
29*4882a593Smuzhiyun 	(NFP_NET_TLS_OPCODE_MASK_RX | NFP_NET_TLS_OPCODE_MASK_TX)
30*4882a593Smuzhiyun 
nfp_net_crypto_set_op(struct nfp_net * nn,u8 opcode,bool on)31*4882a593Smuzhiyun static void nfp_net_crypto_set_op(struct nfp_net *nn, u8 opcode, bool on)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	u32 off, val;
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	off = nn->tlv_caps.crypto_enable_off + round_down(opcode / 8, 4);
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	val = nn_readl(nn, off);
38*4882a593Smuzhiyun 	if (on)
39*4882a593Smuzhiyun 		val |= BIT(opcode & 31);
40*4882a593Smuzhiyun 	else
41*4882a593Smuzhiyun 		val &= ~BIT(opcode & 31);
42*4882a593Smuzhiyun 	nn_writel(nn, off, val);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun static bool
__nfp_net_tls_conn_cnt_changed(struct nfp_net * nn,int add,enum tls_offload_ctx_dir direction)46*4882a593Smuzhiyun __nfp_net_tls_conn_cnt_changed(struct nfp_net *nn, int add,
47*4882a593Smuzhiyun 			       enum tls_offload_ctx_dir direction)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	u8 opcode;
50*4882a593Smuzhiyun 	int cnt;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
53*4882a593Smuzhiyun 		opcode = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC;
54*4882a593Smuzhiyun 		nn->ktls_tx_conn_cnt += add;
55*4882a593Smuzhiyun 		cnt = nn->ktls_tx_conn_cnt;
56*4882a593Smuzhiyun 		nn->dp.ktls_tx = !!nn->ktls_tx_conn_cnt;
57*4882a593Smuzhiyun 	} else {
58*4882a593Smuzhiyun 		opcode = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC;
59*4882a593Smuzhiyun 		nn->ktls_rx_conn_cnt += add;
60*4882a593Smuzhiyun 		cnt = nn->ktls_rx_conn_cnt;
61*4882a593Smuzhiyun 	}
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	/* Care only about 0 -> 1 and 1 -> 0 transitions */
64*4882a593Smuzhiyun 	if (cnt > 1)
65*4882a593Smuzhiyun 		return false;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	nfp_net_crypto_set_op(nn, opcode, cnt);
68*4882a593Smuzhiyun 	return true;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun static int
nfp_net_tls_conn_cnt_changed(struct nfp_net * nn,int add,enum tls_offload_ctx_dir direction)72*4882a593Smuzhiyun nfp_net_tls_conn_cnt_changed(struct nfp_net *nn, int add,
73*4882a593Smuzhiyun 			     enum tls_offload_ctx_dir direction)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	int ret = 0;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	/* Use the BAR lock to protect the connection counts */
78*4882a593Smuzhiyun 	nn_ctrl_bar_lock(nn);
79*4882a593Smuzhiyun 	if (__nfp_net_tls_conn_cnt_changed(nn, add, direction)) {
80*4882a593Smuzhiyun 		ret = __nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_CRYPTO);
81*4882a593Smuzhiyun 		/* Undo the cnt adjustment if failed */
82*4882a593Smuzhiyun 		if (ret)
83*4882a593Smuzhiyun 			__nfp_net_tls_conn_cnt_changed(nn, -add, direction);
84*4882a593Smuzhiyun 	}
85*4882a593Smuzhiyun 	nn_ctrl_bar_unlock(nn);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return ret;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun static int
nfp_net_tls_conn_add(struct nfp_net * nn,enum tls_offload_ctx_dir direction)91*4882a593Smuzhiyun nfp_net_tls_conn_add(struct nfp_net *nn, enum tls_offload_ctx_dir direction)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	return nfp_net_tls_conn_cnt_changed(nn, 1, direction);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun static int
nfp_net_tls_conn_remove(struct nfp_net * nn,enum tls_offload_ctx_dir direction)97*4882a593Smuzhiyun nfp_net_tls_conn_remove(struct nfp_net *nn, enum tls_offload_ctx_dir direction)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	return nfp_net_tls_conn_cnt_changed(nn, -1, direction);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun static struct sk_buff *
nfp_net_tls_alloc_simple(struct nfp_net * nn,size_t req_sz,gfp_t flags)103*4882a593Smuzhiyun nfp_net_tls_alloc_simple(struct nfp_net *nn, size_t req_sz, gfp_t flags)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	return nfp_ccm_mbox_msg_alloc(nn, req_sz,
106*4882a593Smuzhiyun 				      sizeof(struct nfp_crypto_reply_simple),
107*4882a593Smuzhiyun 				      flags);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun static int
nfp_net_tls_communicate_simple(struct nfp_net * nn,struct sk_buff * skb,const char * name,enum nfp_ccm_type type)111*4882a593Smuzhiyun nfp_net_tls_communicate_simple(struct nfp_net *nn, struct sk_buff *skb,
112*4882a593Smuzhiyun 			       const char *name, enum nfp_ccm_type type)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	struct nfp_crypto_reply_simple *reply;
115*4882a593Smuzhiyun 	int err;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	err = __nfp_ccm_mbox_communicate(nn, skb, type,
118*4882a593Smuzhiyun 					 sizeof(*reply), sizeof(*reply),
119*4882a593Smuzhiyun 					 type == NFP_CCM_TYPE_CRYPTO_DEL);
120*4882a593Smuzhiyun 	if (err) {
121*4882a593Smuzhiyun 		nn_dp_warn(&nn->dp, "failed to %s TLS: %d\n", name, err);
122*4882a593Smuzhiyun 		return err;
123*4882a593Smuzhiyun 	}
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	reply = (void *)skb->data;
126*4882a593Smuzhiyun 	err = -be32_to_cpu(reply->error);
127*4882a593Smuzhiyun 	if (err)
128*4882a593Smuzhiyun 		nn_dp_warn(&nn->dp, "failed to %s TLS, fw replied: %d\n",
129*4882a593Smuzhiyun 			   name, err);
130*4882a593Smuzhiyun 	dev_consume_skb_any(skb);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	return err;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
nfp_net_tls_del_fw(struct nfp_net * nn,__be32 * fw_handle)135*4882a593Smuzhiyun static void nfp_net_tls_del_fw(struct nfp_net *nn, __be32 *fw_handle)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	struct nfp_crypto_req_del *req;
138*4882a593Smuzhiyun 	struct sk_buff *skb;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), GFP_KERNEL);
141*4882a593Smuzhiyun 	if (!skb)
142*4882a593Smuzhiyun 		return;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	req = (void *)skb->data;
145*4882a593Smuzhiyun 	req->ep_id = 0;
146*4882a593Smuzhiyun 	memcpy(req->handle, fw_handle, sizeof(req->handle));
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	nfp_net_tls_communicate_simple(nn, skb, "delete",
149*4882a593Smuzhiyun 				       NFP_CCM_TYPE_CRYPTO_DEL);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun static void
nfp_net_tls_set_ipver_vlan(struct nfp_crypto_req_add_front * front,u8 ipver)153*4882a593Smuzhiyun nfp_net_tls_set_ipver_vlan(struct nfp_crypto_req_add_front *front, u8 ipver)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	front->ipver_vlan = cpu_to_be16(FIELD_PREP(NFP_NET_TLS_IPVER, ipver) |
156*4882a593Smuzhiyun 					FIELD_PREP(NFP_NET_TLS_VLAN,
157*4882a593Smuzhiyun 						   NFP_NET_TLS_VLAN_UNUSED));
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun static void
nfp_net_tls_assign_conn_id(struct nfp_net * nn,struct nfp_crypto_req_add_front * front)161*4882a593Smuzhiyun nfp_net_tls_assign_conn_id(struct nfp_net *nn,
162*4882a593Smuzhiyun 			   struct nfp_crypto_req_add_front *front)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	u32 len;
165*4882a593Smuzhiyun 	u64 id;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	id = atomic64_inc_return(&nn->ktls_conn_id_gen);
168*4882a593Smuzhiyun 	len = front->key_len - NFP_NET_TLS_NON_ADDR_KEY_LEN;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	memcpy(front->l3_addrs, &id, sizeof(id));
171*4882a593Smuzhiyun 	memset(front->l3_addrs + sizeof(id), 0, len - sizeof(id));
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun static struct nfp_crypto_req_add_back *
nfp_net_tls_set_ipv4(struct nfp_net * nn,struct nfp_crypto_req_add_v4 * req,struct sock * sk,int direction)175*4882a593Smuzhiyun nfp_net_tls_set_ipv4(struct nfp_net *nn, struct nfp_crypto_req_add_v4 *req,
176*4882a593Smuzhiyun 		     struct sock *sk, int direction)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	struct inet_sock *inet = inet_sk(sk);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	req->front.key_len += sizeof(__be32) * 2;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
183*4882a593Smuzhiyun 		nfp_net_tls_assign_conn_id(nn, &req->front);
184*4882a593Smuzhiyun 	} else {
185*4882a593Smuzhiyun 		req->src_ip = inet->inet_daddr;
186*4882a593Smuzhiyun 		req->dst_ip = inet->inet_saddr;
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	return &req->back;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun static struct nfp_crypto_req_add_back *
nfp_net_tls_set_ipv6(struct nfp_net * nn,struct nfp_crypto_req_add_v6 * req,struct sock * sk,int direction)193*4882a593Smuzhiyun nfp_net_tls_set_ipv6(struct nfp_net *nn, struct nfp_crypto_req_add_v6 *req,
194*4882a593Smuzhiyun 		     struct sock *sk, int direction)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
197*4882a593Smuzhiyun 	struct ipv6_pinfo *np = inet6_sk(sk);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	req->front.key_len += sizeof(struct in6_addr) * 2;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
202*4882a593Smuzhiyun 		nfp_net_tls_assign_conn_id(nn, &req->front);
203*4882a593Smuzhiyun 	} else {
204*4882a593Smuzhiyun 		memcpy(req->src_ip, &sk->sk_v6_daddr, sizeof(req->src_ip));
205*4882a593Smuzhiyun 		memcpy(req->dst_ip, &np->saddr, sizeof(req->dst_ip));
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun #endif
209*4882a593Smuzhiyun 	return &req->back;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun static void
nfp_net_tls_set_l4(struct nfp_crypto_req_add_front * front,struct nfp_crypto_req_add_back * back,struct sock * sk,int direction)213*4882a593Smuzhiyun nfp_net_tls_set_l4(struct nfp_crypto_req_add_front *front,
214*4882a593Smuzhiyun 		   struct nfp_crypto_req_add_back *back, struct sock *sk,
215*4882a593Smuzhiyun 		   int direction)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun 	struct inet_sock *inet = inet_sk(sk);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	front->l4_proto = IPPROTO_TCP;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
222*4882a593Smuzhiyun 		back->src_port = 0;
223*4882a593Smuzhiyun 		back->dst_port = 0;
224*4882a593Smuzhiyun 	} else {
225*4882a593Smuzhiyun 		back->src_port = inet->inet_dport;
226*4882a593Smuzhiyun 		back->dst_port = inet->inet_sport;
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun 
nfp_tls_1_2_dir_to_opcode(enum tls_offload_ctx_dir direction)230*4882a593Smuzhiyun static u8 nfp_tls_1_2_dir_to_opcode(enum tls_offload_ctx_dir direction)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	switch (direction) {
233*4882a593Smuzhiyun 	case TLS_OFFLOAD_CTX_DIR_TX:
234*4882a593Smuzhiyun 		return NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC;
235*4882a593Smuzhiyun 	case TLS_OFFLOAD_CTX_DIR_RX:
236*4882a593Smuzhiyun 		return NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC;
237*4882a593Smuzhiyun 	default:
238*4882a593Smuzhiyun 		WARN_ON_ONCE(1);
239*4882a593Smuzhiyun 		return 0;
240*4882a593Smuzhiyun 	}
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun static bool
nfp_net_cipher_supported(struct nfp_net * nn,u16 cipher_type,enum tls_offload_ctx_dir direction)244*4882a593Smuzhiyun nfp_net_cipher_supported(struct nfp_net *nn, u16 cipher_type,
245*4882a593Smuzhiyun 			 enum tls_offload_ctx_dir direction)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	u8 bit;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	switch (cipher_type) {
250*4882a593Smuzhiyun 	case TLS_CIPHER_AES_GCM_128:
251*4882a593Smuzhiyun 		if (direction == TLS_OFFLOAD_CTX_DIR_TX)
252*4882a593Smuzhiyun 			bit = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_ENC;
253*4882a593Smuzhiyun 		else
254*4882a593Smuzhiyun 			bit = NFP_NET_CRYPTO_OP_TLS_1_2_AES_GCM_128_DEC;
255*4882a593Smuzhiyun 		break;
256*4882a593Smuzhiyun 	default:
257*4882a593Smuzhiyun 		return false;
258*4882a593Smuzhiyun 	}
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	return nn->tlv_caps.crypto_ops & BIT(bit);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun static int
nfp_net_tls_add(struct net_device * netdev,struct sock * sk,enum tls_offload_ctx_dir direction,struct tls_crypto_info * crypto_info,u32 start_offload_tcp_sn)264*4882a593Smuzhiyun nfp_net_tls_add(struct net_device *netdev, struct sock *sk,
265*4882a593Smuzhiyun 		enum tls_offload_ctx_dir direction,
266*4882a593Smuzhiyun 		struct tls_crypto_info *crypto_info,
267*4882a593Smuzhiyun 		u32 start_offload_tcp_sn)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun 	struct tls12_crypto_info_aes_gcm_128 *tls_ci;
270*4882a593Smuzhiyun 	struct nfp_net *nn = netdev_priv(netdev);
271*4882a593Smuzhiyun 	struct nfp_crypto_req_add_front *front;
272*4882a593Smuzhiyun 	struct nfp_net_tls_offload_ctx *ntls;
273*4882a593Smuzhiyun 	struct nfp_crypto_req_add_back *back;
274*4882a593Smuzhiyun 	struct nfp_crypto_reply_add *reply;
275*4882a593Smuzhiyun 	struct sk_buff *skb;
276*4882a593Smuzhiyun 	size_t req_sz;
277*4882a593Smuzhiyun 	void *req;
278*4882a593Smuzhiyun 	bool ipv6;
279*4882a593Smuzhiyun 	int err;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	BUILD_BUG_ON(sizeof(struct nfp_net_tls_offload_ctx) >
282*4882a593Smuzhiyun 		     TLS_DRIVER_STATE_SIZE_TX);
283*4882a593Smuzhiyun 	BUILD_BUG_ON(offsetof(struct nfp_net_tls_offload_ctx, rx_end) >
284*4882a593Smuzhiyun 		     TLS_DRIVER_STATE_SIZE_RX);
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	if (!nfp_net_cipher_supported(nn, crypto_info->cipher_type, direction))
287*4882a593Smuzhiyun 		return -EOPNOTSUPP;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	switch (sk->sk_family) {
290*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
291*4882a593Smuzhiyun 	case AF_INET6:
292*4882a593Smuzhiyun 		if (sk->sk_ipv6only ||
293*4882a593Smuzhiyun 		    ipv6_addr_type(&sk->sk_v6_daddr) != IPV6_ADDR_MAPPED) {
294*4882a593Smuzhiyun 			req_sz = sizeof(struct nfp_crypto_req_add_v6);
295*4882a593Smuzhiyun 			ipv6 = true;
296*4882a593Smuzhiyun 			break;
297*4882a593Smuzhiyun 		}
298*4882a593Smuzhiyun #endif
299*4882a593Smuzhiyun 		fallthrough;
300*4882a593Smuzhiyun 	case AF_INET:
301*4882a593Smuzhiyun 		req_sz = sizeof(struct nfp_crypto_req_add_v4);
302*4882a593Smuzhiyun 		ipv6 = false;
303*4882a593Smuzhiyun 		break;
304*4882a593Smuzhiyun 	default:
305*4882a593Smuzhiyun 		return -EOPNOTSUPP;
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	err = nfp_net_tls_conn_add(nn, direction);
309*4882a593Smuzhiyun 	if (err)
310*4882a593Smuzhiyun 		return err;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	skb = nfp_ccm_mbox_msg_alloc(nn, req_sz, sizeof(*reply), GFP_KERNEL);
313*4882a593Smuzhiyun 	if (!skb) {
314*4882a593Smuzhiyun 		err = -ENOMEM;
315*4882a593Smuzhiyun 		goto err_conn_remove;
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	front = (void *)skb->data;
319*4882a593Smuzhiyun 	front->ep_id = 0;
320*4882a593Smuzhiyun 	front->key_len = NFP_NET_TLS_NON_ADDR_KEY_LEN;
321*4882a593Smuzhiyun 	front->opcode = nfp_tls_1_2_dir_to_opcode(direction);
322*4882a593Smuzhiyun 	memset(front->resv, 0, sizeof(front->resv));
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	nfp_net_tls_set_ipver_vlan(front, ipv6 ? 6 : 4);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	req = (void *)skb->data;
327*4882a593Smuzhiyun 	if (ipv6)
328*4882a593Smuzhiyun 		back = nfp_net_tls_set_ipv6(nn, req, sk, direction);
329*4882a593Smuzhiyun 	else
330*4882a593Smuzhiyun 		back = nfp_net_tls_set_ipv4(nn, req, sk, direction);
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	nfp_net_tls_set_l4(front, back, sk, direction);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	back->counter = 0;
335*4882a593Smuzhiyun 	back->tcp_seq = cpu_to_be32(start_offload_tcp_sn);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	tls_ci = (struct tls12_crypto_info_aes_gcm_128 *)crypto_info;
338*4882a593Smuzhiyun 	memcpy(back->key, tls_ci->key, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
339*4882a593Smuzhiyun 	memset(&back->key[TLS_CIPHER_AES_GCM_128_KEY_SIZE / 4], 0,
340*4882a593Smuzhiyun 	       sizeof(back->key) - TLS_CIPHER_AES_GCM_128_KEY_SIZE);
341*4882a593Smuzhiyun 	memcpy(back->iv, tls_ci->iv, TLS_CIPHER_AES_GCM_128_IV_SIZE);
342*4882a593Smuzhiyun 	memcpy(&back->salt, tls_ci->salt, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
343*4882a593Smuzhiyun 	memcpy(back->rec_no, tls_ci->rec_seq, sizeof(tls_ci->rec_seq));
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	/* Get an extra ref on the skb so we can wipe the key after */
346*4882a593Smuzhiyun 	skb_get(skb);
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	err = nfp_ccm_mbox_communicate(nn, skb, NFP_CCM_TYPE_CRYPTO_ADD,
349*4882a593Smuzhiyun 				       sizeof(*reply), sizeof(*reply));
350*4882a593Smuzhiyun 	reply = (void *)skb->data;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	/* We depend on CCM MBOX code not reallocating skb we sent
353*4882a593Smuzhiyun 	 * so we can clear the key material out of the memory.
354*4882a593Smuzhiyun 	 */
355*4882a593Smuzhiyun 	if (!WARN_ON_ONCE((u8 *)back < skb->head ||
356*4882a593Smuzhiyun 			  (u8 *)back > skb_end_pointer(skb)) &&
357*4882a593Smuzhiyun 	    !WARN_ON_ONCE((u8 *)&reply[1] > (u8 *)back))
358*4882a593Smuzhiyun 		memzero_explicit(back, sizeof(*back));
359*4882a593Smuzhiyun 	dev_consume_skb_any(skb); /* the extra ref from skb_get() above */
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	if (err) {
362*4882a593Smuzhiyun 		nn_dp_warn(&nn->dp, "failed to add TLS: %d (%d)\n",
363*4882a593Smuzhiyun 			   err, direction == TLS_OFFLOAD_CTX_DIR_TX);
364*4882a593Smuzhiyun 		/* communicate frees skb on error */
365*4882a593Smuzhiyun 		goto err_conn_remove;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	err = -be32_to_cpu(reply->error);
369*4882a593Smuzhiyun 	if (err) {
370*4882a593Smuzhiyun 		if (err == -ENOSPC) {
371*4882a593Smuzhiyun 			if (!atomic_fetch_inc(&nn->ktls_no_space))
372*4882a593Smuzhiyun 				nn_info(nn, "HW TLS table full\n");
373*4882a593Smuzhiyun 		} else {
374*4882a593Smuzhiyun 			nn_dp_warn(&nn->dp,
375*4882a593Smuzhiyun 				   "failed to add TLS, FW replied: %d\n", err);
376*4882a593Smuzhiyun 		}
377*4882a593Smuzhiyun 		goto err_free_skb;
378*4882a593Smuzhiyun 	}
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	if (!reply->handle[0] && !reply->handle[1]) {
381*4882a593Smuzhiyun 		nn_dp_warn(&nn->dp, "FW returned NULL handle\n");
382*4882a593Smuzhiyun 		err = -EINVAL;
383*4882a593Smuzhiyun 		goto err_fw_remove;
384*4882a593Smuzhiyun 	}
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	ntls = tls_driver_ctx(sk, direction);
387*4882a593Smuzhiyun 	memcpy(ntls->fw_handle, reply->handle, sizeof(ntls->fw_handle));
388*4882a593Smuzhiyun 	if (direction == TLS_OFFLOAD_CTX_DIR_TX)
389*4882a593Smuzhiyun 		ntls->next_seq = start_offload_tcp_sn;
390*4882a593Smuzhiyun 	dev_consume_skb_any(skb);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	if (direction == TLS_OFFLOAD_CTX_DIR_TX)
393*4882a593Smuzhiyun 		return 0;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	if (!nn->tlv_caps.tls_resync_ss)
396*4882a593Smuzhiyun 		tls_offload_rx_resync_set_type(sk, TLS_OFFLOAD_SYNC_TYPE_CORE_NEXT_HINT);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	return 0;
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun err_fw_remove:
401*4882a593Smuzhiyun 	nfp_net_tls_del_fw(nn, reply->handle);
402*4882a593Smuzhiyun err_free_skb:
403*4882a593Smuzhiyun 	dev_consume_skb_any(skb);
404*4882a593Smuzhiyun err_conn_remove:
405*4882a593Smuzhiyun 	nfp_net_tls_conn_remove(nn, direction);
406*4882a593Smuzhiyun 	return err;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun static void
nfp_net_tls_del(struct net_device * netdev,struct tls_context * tls_ctx,enum tls_offload_ctx_dir direction)410*4882a593Smuzhiyun nfp_net_tls_del(struct net_device *netdev, struct tls_context *tls_ctx,
411*4882a593Smuzhiyun 		enum tls_offload_ctx_dir direction)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	struct nfp_net *nn = netdev_priv(netdev);
414*4882a593Smuzhiyun 	struct nfp_net_tls_offload_ctx *ntls;
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	nfp_net_tls_conn_remove(nn, direction);
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	ntls = __tls_driver_ctx(tls_ctx, direction);
419*4882a593Smuzhiyun 	nfp_net_tls_del_fw(nn, ntls->fw_handle);
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun static int
nfp_net_tls_resync(struct net_device * netdev,struct sock * sk,u32 seq,u8 * rcd_sn,enum tls_offload_ctx_dir direction)423*4882a593Smuzhiyun nfp_net_tls_resync(struct net_device *netdev, struct sock *sk, u32 seq,
424*4882a593Smuzhiyun 		   u8 *rcd_sn, enum tls_offload_ctx_dir direction)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun 	struct nfp_net *nn = netdev_priv(netdev);
427*4882a593Smuzhiyun 	struct nfp_net_tls_offload_ctx *ntls;
428*4882a593Smuzhiyun 	struct nfp_crypto_req_update *req;
429*4882a593Smuzhiyun 	enum nfp_ccm_type type;
430*4882a593Smuzhiyun 	struct sk_buff *skb;
431*4882a593Smuzhiyun 	gfp_t flags;
432*4882a593Smuzhiyun 	int err;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	flags = direction == TLS_OFFLOAD_CTX_DIR_TX ? GFP_KERNEL : GFP_ATOMIC;
435*4882a593Smuzhiyun 	skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), flags);
436*4882a593Smuzhiyun 	if (!skb)
437*4882a593Smuzhiyun 		return -ENOMEM;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	ntls = tls_driver_ctx(sk, direction);
440*4882a593Smuzhiyun 	req = (void *)skb->data;
441*4882a593Smuzhiyun 	req->ep_id = 0;
442*4882a593Smuzhiyun 	req->opcode = nfp_tls_1_2_dir_to_opcode(direction);
443*4882a593Smuzhiyun 	memset(req->resv, 0, sizeof(req->resv));
444*4882a593Smuzhiyun 	memcpy(req->handle, ntls->fw_handle, sizeof(ntls->fw_handle));
445*4882a593Smuzhiyun 	req->tcp_seq = cpu_to_be32(seq);
446*4882a593Smuzhiyun 	memcpy(req->rec_no, rcd_sn, sizeof(req->rec_no));
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	type = NFP_CCM_TYPE_CRYPTO_UPDATE;
449*4882a593Smuzhiyun 	if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
450*4882a593Smuzhiyun 		err = nfp_net_tls_communicate_simple(nn, skb, "sync", type);
451*4882a593Smuzhiyun 		if (err)
452*4882a593Smuzhiyun 			return err;
453*4882a593Smuzhiyun 		ntls->next_seq = seq;
454*4882a593Smuzhiyun 	} else {
455*4882a593Smuzhiyun 		if (nn->tlv_caps.tls_resync_ss)
456*4882a593Smuzhiyun 			type = NFP_CCM_TYPE_CRYPTO_RESYNC;
457*4882a593Smuzhiyun 		nfp_ccm_mbox_post(nn, skb, type,
458*4882a593Smuzhiyun 				  sizeof(struct nfp_crypto_reply_simple));
459*4882a593Smuzhiyun 		atomic_inc(&nn->ktls_rx_resync_sent);
460*4882a593Smuzhiyun 	}
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	return 0;
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun static const struct tlsdev_ops nfp_net_tls_ops = {
466*4882a593Smuzhiyun 	.tls_dev_add = nfp_net_tls_add,
467*4882a593Smuzhiyun 	.tls_dev_del = nfp_net_tls_del,
468*4882a593Smuzhiyun 	.tls_dev_resync = nfp_net_tls_resync,
469*4882a593Smuzhiyun };
470*4882a593Smuzhiyun 
nfp_net_tls_rx_resync_req(struct net_device * netdev,struct nfp_net_tls_resync_req * req,void * pkt,unsigned int pkt_len)471*4882a593Smuzhiyun int nfp_net_tls_rx_resync_req(struct net_device *netdev,
472*4882a593Smuzhiyun 			      struct nfp_net_tls_resync_req *req,
473*4882a593Smuzhiyun 			      void *pkt, unsigned int pkt_len)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun 	struct nfp_net *nn = netdev_priv(netdev);
476*4882a593Smuzhiyun 	struct nfp_net_tls_offload_ctx *ntls;
477*4882a593Smuzhiyun 	struct ipv6hdr *ipv6h;
478*4882a593Smuzhiyun 	struct tcphdr *th;
479*4882a593Smuzhiyun 	struct iphdr *iph;
480*4882a593Smuzhiyun 	struct sock *sk;
481*4882a593Smuzhiyun 	__be32 tcp_seq;
482*4882a593Smuzhiyun 	int err;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	iph = pkt + req->l3_offset;
485*4882a593Smuzhiyun 	ipv6h = pkt + req->l3_offset;
486*4882a593Smuzhiyun 	th = pkt + req->l4_offset;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	if ((u8 *)&th[1] > (u8 *)pkt + pkt_len) {
489*4882a593Smuzhiyun 		netdev_warn_once(netdev, "invalid TLS RX resync request (l3_off: %hhu l4_off: %hhu pkt_len: %u)\n",
490*4882a593Smuzhiyun 				 req->l3_offset, req->l4_offset, pkt_len);
491*4882a593Smuzhiyun 		err = -EINVAL;
492*4882a593Smuzhiyun 		goto err_cnt_ign;
493*4882a593Smuzhiyun 	}
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	switch (iph->version) {
496*4882a593Smuzhiyun 	case 4:
497*4882a593Smuzhiyun 		sk = inet_lookup_established(dev_net(netdev), &tcp_hashinfo,
498*4882a593Smuzhiyun 					     iph->saddr, th->source, iph->daddr,
499*4882a593Smuzhiyun 					     th->dest, netdev->ifindex);
500*4882a593Smuzhiyun 		break;
501*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_IPV6)
502*4882a593Smuzhiyun 	case 6:
503*4882a593Smuzhiyun 		sk = __inet6_lookup_established(dev_net(netdev), &tcp_hashinfo,
504*4882a593Smuzhiyun 						&ipv6h->saddr, th->source,
505*4882a593Smuzhiyun 						&ipv6h->daddr, ntohs(th->dest),
506*4882a593Smuzhiyun 						netdev->ifindex, 0);
507*4882a593Smuzhiyun 		break;
508*4882a593Smuzhiyun #endif
509*4882a593Smuzhiyun 	default:
510*4882a593Smuzhiyun 		netdev_warn_once(netdev, "invalid TLS RX resync request (l3_off: %hhu l4_off: %hhu ipver: %u)\n",
511*4882a593Smuzhiyun 				 req->l3_offset, req->l4_offset, iph->version);
512*4882a593Smuzhiyun 		err = -EINVAL;
513*4882a593Smuzhiyun 		goto err_cnt_ign;
514*4882a593Smuzhiyun 	}
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	err = 0;
517*4882a593Smuzhiyun 	if (!sk)
518*4882a593Smuzhiyun 		goto err_cnt_ign;
519*4882a593Smuzhiyun 	if (!tls_is_sk_rx_device_offloaded(sk) ||
520*4882a593Smuzhiyun 	    sk->sk_shutdown & RCV_SHUTDOWN)
521*4882a593Smuzhiyun 		goto err_put_sock;
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	ntls = tls_driver_ctx(sk, TLS_OFFLOAD_CTX_DIR_RX);
524*4882a593Smuzhiyun 	/* some FW versions can't report the handle and report 0s */
525*4882a593Smuzhiyun 	if (memchr_inv(&req->fw_handle, 0, sizeof(req->fw_handle)) &&
526*4882a593Smuzhiyun 	    memcmp(&req->fw_handle, &ntls->fw_handle, sizeof(ntls->fw_handle)))
527*4882a593Smuzhiyun 		goto err_put_sock;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	/* copy to ensure alignment */
530*4882a593Smuzhiyun 	memcpy(&tcp_seq, &req->tcp_seq, sizeof(tcp_seq));
531*4882a593Smuzhiyun 	tls_offload_rx_resync_request(sk, tcp_seq);
532*4882a593Smuzhiyun 	atomic_inc(&nn->ktls_rx_resync_req);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	sock_gen_put(sk);
535*4882a593Smuzhiyun 	return 0;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun err_put_sock:
538*4882a593Smuzhiyun 	sock_gen_put(sk);
539*4882a593Smuzhiyun err_cnt_ign:
540*4882a593Smuzhiyun 	atomic_inc(&nn->ktls_rx_resync_ign);
541*4882a593Smuzhiyun 	return err;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun 
nfp_net_tls_reset(struct nfp_net * nn)544*4882a593Smuzhiyun static int nfp_net_tls_reset(struct nfp_net *nn)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun 	struct nfp_crypto_req_reset *req;
547*4882a593Smuzhiyun 	struct sk_buff *skb;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	skb = nfp_net_tls_alloc_simple(nn, sizeof(*req), GFP_KERNEL);
550*4882a593Smuzhiyun 	if (!skb)
551*4882a593Smuzhiyun 		return -ENOMEM;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	req = (void *)skb->data;
554*4882a593Smuzhiyun 	req->ep_id = 0;
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	return nfp_net_tls_communicate_simple(nn, skb, "reset",
557*4882a593Smuzhiyun 					      NFP_CCM_TYPE_CRYPTO_RESET);
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun 
nfp_net_tls_init(struct nfp_net * nn)560*4882a593Smuzhiyun int nfp_net_tls_init(struct nfp_net *nn)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun 	struct net_device *netdev = nn->dp.netdev;
563*4882a593Smuzhiyun 	int err;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	if (!(nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK))
566*4882a593Smuzhiyun 		return 0;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	if ((nn->tlv_caps.mbox_cmsg_types & NFP_NET_TLS_CCM_MBOX_OPS_MASK) !=
569*4882a593Smuzhiyun 	    NFP_NET_TLS_CCM_MBOX_OPS_MASK)
570*4882a593Smuzhiyun 		return 0;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	if (!nfp_ccm_mbox_fits(nn, sizeof(struct nfp_crypto_req_add_v6))) {
573*4882a593Smuzhiyun 		nn_warn(nn, "disabling TLS offload - mbox too small: %d\n",
574*4882a593Smuzhiyun 			nn->tlv_caps.mbox_len);
575*4882a593Smuzhiyun 		return 0;
576*4882a593Smuzhiyun 	}
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	err = nfp_net_tls_reset(nn);
579*4882a593Smuzhiyun 	if (err)
580*4882a593Smuzhiyun 		return err;
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	nn_ctrl_bar_lock(nn);
583*4882a593Smuzhiyun 	nn_writel(nn, nn->tlv_caps.crypto_enable_off, 0);
584*4882a593Smuzhiyun 	err = __nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_CRYPTO);
585*4882a593Smuzhiyun 	nn_ctrl_bar_unlock(nn);
586*4882a593Smuzhiyun 	if (err)
587*4882a593Smuzhiyun 		return err;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	if (nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK_RX) {
590*4882a593Smuzhiyun 		netdev->hw_features |= NETIF_F_HW_TLS_RX;
591*4882a593Smuzhiyun 		netdev->features |= NETIF_F_HW_TLS_RX;
592*4882a593Smuzhiyun 	}
593*4882a593Smuzhiyun 	if (nn->tlv_caps.crypto_ops & NFP_NET_TLS_OPCODE_MASK_TX) {
594*4882a593Smuzhiyun 		netdev->hw_features |= NETIF_F_HW_TLS_TX;
595*4882a593Smuzhiyun 		netdev->features |= NETIF_F_HW_TLS_TX;
596*4882a593Smuzhiyun 	}
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	netdev->tlsdev_ops = &nfp_net_tls_ops;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	return 0;
601*4882a593Smuzhiyun }
602