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