crypto/cnxk: remove redundant code
[dpdk.git] / drivers / crypto / cnxk / cn10k_ipsec.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include <rte_malloc.h>
6 #include <rte_cryptodev.h>
7 #include <rte_esp.h>
8 #include <rte_ip.h>
9 #include <rte_security.h>
10 #include <rte_security_driver.h>
11 #include <rte_udp.h>
12
13 #include "cnxk_cryptodev.h"
14 #include "cnxk_ipsec.h"
15 #include "cnxk_security.h"
16 #include "cn10k_ipsec.h"
17
18 #include "roc_api.h"
19
20 static int
21 ipsec_xform_cipher_verify(struct rte_crypto_sym_xform *xform)
22 {
23         if (xform->cipher.algo == RTE_CRYPTO_CIPHER_AES_CBC) {
24                 switch (xform->cipher.key.length) {
25                 case 16:
26                 case 24:
27                 case 32:
28                         break;
29                 default:
30                         return -ENOTSUP;
31                 }
32                 return 0;
33         }
34
35         return -ENOTSUP;
36 }
37
38 static int
39 ipsec_xform_auth_verify(struct rte_crypto_sym_xform *xform)
40 {
41         uint16_t keylen = xform->auth.key.length;
42
43         if (xform->auth.algo == RTE_CRYPTO_AUTH_SHA1_HMAC) {
44                 if (keylen >= 20 && keylen <= 64)
45                         return 0;
46         }
47
48         return -ENOTSUP;
49 }
50
51 static int
52 ipsec_xform_aead_verify(struct rte_security_ipsec_xform *ipsec_xfrm,
53                         struct rte_crypto_sym_xform *crypto_xfrm)
54 {
55         if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
56             crypto_xfrm->aead.op != RTE_CRYPTO_AEAD_OP_ENCRYPT)
57                 return -EINVAL;
58
59         if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
60             crypto_xfrm->aead.op != RTE_CRYPTO_AEAD_OP_DECRYPT)
61                 return -EINVAL;
62
63         if (crypto_xfrm->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) {
64                 switch (crypto_xfrm->aead.key.length) {
65                 case ROC_CPT_AES128_KEY_LEN:
66                 case ROC_CPT_AES192_KEY_LEN:
67                 case ROC_CPT_AES256_KEY_LEN:
68                         break;
69                 default:
70                         return -EINVAL;
71                 }
72                 return 0;
73         }
74
75         return -ENOTSUP;
76 }
77
78 static int
79 cn10k_ipsec_xform_verify(struct rte_security_ipsec_xform *ipsec_xfrm,
80                          struct rte_crypto_sym_xform *crypto_xfrm)
81 {
82         struct rte_crypto_sym_xform *auth_xform, *cipher_xform;
83         int ret;
84
85         if ((ipsec_xfrm->direction != RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
86             (ipsec_xfrm->direction != RTE_SECURITY_IPSEC_SA_DIR_EGRESS))
87                 return -EINVAL;
88
89         if ((ipsec_xfrm->proto != RTE_SECURITY_IPSEC_SA_PROTO_ESP) &&
90             (ipsec_xfrm->proto != RTE_SECURITY_IPSEC_SA_PROTO_AH))
91                 return -EINVAL;
92
93         if ((ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) &&
94             (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL))
95                 return -EINVAL;
96
97         if ((ipsec_xfrm->tunnel.type != RTE_SECURITY_IPSEC_TUNNEL_IPV4) &&
98             (ipsec_xfrm->tunnel.type != RTE_SECURITY_IPSEC_TUNNEL_IPV6))
99                 return -EINVAL;
100
101         if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD)
102                 return ipsec_xform_aead_verify(ipsec_xfrm, crypto_xfrm);
103
104         if (crypto_xfrm->next == NULL)
105                 return -EINVAL;
106
107         if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
108                 /* Ingress */
109                 if (crypto_xfrm->type != RTE_CRYPTO_SYM_XFORM_AUTH ||
110                     crypto_xfrm->next->type != RTE_CRYPTO_SYM_XFORM_CIPHER)
111                         return -EINVAL;
112                 auth_xform = crypto_xfrm;
113                 cipher_xform = crypto_xfrm->next;
114         } else {
115                 /* Egress */
116                 if (crypto_xfrm->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
117                     crypto_xfrm->next->type != RTE_CRYPTO_SYM_XFORM_AUTH)
118                         return -EINVAL;
119                 cipher_xform = crypto_xfrm;
120                 auth_xform = crypto_xfrm->next;
121         }
122
123         ret = ipsec_xform_cipher_verify(cipher_xform);
124         if (ret)
125                 return ret;
126
127         ret = ipsec_xform_auth_verify(auth_xform);
128         if (ret)
129                 return ret;
130
131         return 0;
132 }
133
134 static uint64_t
135 ipsec_cpt_inst_w7_get(struct roc_cpt *roc_cpt, void *sa)
136 {
137         union cpt_inst_w7 w7;
138
139         w7.u64 = 0;
140         w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_IE];
141         w7.s.ctx_val = 1;
142         w7.s.cptr = (uint64_t)sa;
143         rte_mb();
144
145         return w7.u64;
146 }
147
148 static int
149 cn10k_ipsec_outb_sa_create(struct roc_cpt *roc_cpt,
150                            struct rte_security_ipsec_xform *ipsec_xfrm,
151                            struct rte_crypto_sym_xform *crypto_xfrm,
152                            struct rte_security_session *sec_sess)
153 {
154         struct roc_ot_ipsec_outb_sa *out_sa;
155         struct cnxk_ipsec_outb_rlens rlens;
156         struct cn10k_sec_session *sess;
157         struct cn10k_ipsec_sa *sa;
158         union cpt_inst_w4 inst_w4;
159         int ret;
160
161         sess = get_sec_session_private_data(sec_sess);
162         sa = &sess->sa;
163         out_sa = &sa->out_sa;
164
165         memset(out_sa, 0, sizeof(struct roc_ot_ipsec_outb_sa));
166
167         /* Translate security parameters to SA */
168         ret = cnxk_ot_ipsec_outb_sa_fill(out_sa, ipsec_xfrm, crypto_xfrm);
169         if (ret)
170                 return ret;
171
172         sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
173
174         /* Get Rlen calculation data */
175         ret = cnxk_ipsec_outb_rlens_get(&rlens, ipsec_xfrm, crypto_xfrm);
176         if (ret)
177                 return ret;
178
179         sa->partial_len = rlens.partial_len;
180         sa->roundup_byte = rlens.roundup_byte;
181         sa->roundup_len = rlens.roundup_len;
182
183         /* pre-populate CPT INST word 4 */
184         inst_w4.u64 = 0;
185         inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC;
186         inst_w4.s.param1 = 0;
187         sa->inst.w4 = inst_w4.u64;
188
189         return 0;
190 }
191
192 static int
193 cn10k_ipsec_inb_sa_create(struct roc_cpt *roc_cpt,
194                           struct rte_security_ipsec_xform *ipsec_xfrm,
195                           struct rte_crypto_sym_xform *crypto_xfrm,
196                           struct rte_security_session *sec_sess)
197 {
198         struct roc_ot_ipsec_inb_sa *in_sa;
199         struct cn10k_sec_session *sess;
200         struct cn10k_ipsec_sa *sa;
201         union cpt_inst_w4 inst_w4;
202         int ret;
203
204         sess = get_sec_session_private_data(sec_sess);
205         sa = &sess->sa;
206         in_sa = &sa->in_sa;
207
208         /* Translate security parameters to SA */
209         ret = cnxk_ot_ipsec_inb_sa_fill(in_sa, ipsec_xfrm, crypto_xfrm);
210         if (ret)
211                 return ret;
212
213         /* TODO add support for antireplay */
214         sa->in_sa.w0.s.ar_win = 0;
215
216         /* TODO add support for udp encap */
217
218         sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
219
220         /* pre-populate CPT INST word 4 */
221         inst_w4.u64 = 0;
222         inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_INBOUND_IPSEC;
223
224         /* Disable checksum verification for now */
225         inst_w4.s.param1 = 7;
226         sa->inst.w4 = inst_w4.u64;
227
228         return 0;
229 }
230
231 static int
232 cn10k_ipsec_session_create(void *dev,
233                            struct rte_security_ipsec_xform *ipsec_xfrm,
234                            struct rte_crypto_sym_xform *crypto_xfrm,
235                            struct rte_security_session *sess)
236 {
237         struct rte_cryptodev *crypto_dev = dev;
238         struct roc_cpt *roc_cpt;
239         struct cnxk_cpt_vf *vf;
240         int ret;
241
242         vf = crypto_dev->data->dev_private;
243         roc_cpt = &vf->cpt;
244
245         if (crypto_dev->data->queue_pairs[0] == NULL) {
246                 plt_err("Setup cpt queue pair before creating security session");
247                 return -EPERM;
248         }
249
250         ret = cn10k_ipsec_xform_verify(ipsec_xfrm, crypto_xfrm);
251         if (ret)
252                 return ret;
253
254         if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
255                 return cn10k_ipsec_inb_sa_create(roc_cpt, ipsec_xfrm,
256                                                  crypto_xfrm, sess);
257         else
258                 return cn10k_ipsec_outb_sa_create(roc_cpt, ipsec_xfrm,
259                                                   crypto_xfrm, sess);
260 }
261
262 static int
263 cn10k_sec_session_create(void *device, struct rte_security_session_conf *conf,
264                          struct rte_security_session *sess,
265                          struct rte_mempool *mempool)
266 {
267         struct cn10k_sec_session *priv;
268         int ret;
269
270         if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
271                 return -EINVAL;
272
273         if (rte_mempool_get(mempool, (void **)&priv)) {
274                 plt_err("Could not allocate security session private data");
275                 return -ENOMEM;
276         }
277
278         set_sec_session_private_data(sess, priv);
279
280         if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
281                 ret = -ENOTSUP;
282                 goto mempool_put;
283         }
284         ret = cn10k_ipsec_session_create(device, &conf->ipsec,
285                                          conf->crypto_xform, sess);
286         if (ret)
287                 goto mempool_put;
288
289         return 0;
290
291 mempool_put:
292         rte_mempool_put(mempool, priv);
293         set_sec_session_private_data(sess, NULL);
294         return ret;
295 }
296
297 static int
298 cn10k_sec_session_destroy(void *device __rte_unused,
299                           struct rte_security_session *sess)
300 {
301         struct cn10k_sec_session *priv;
302         struct rte_mempool *sess_mp;
303
304         priv = get_sec_session_private_data(sess);
305
306         if (priv == NULL)
307                 return 0;
308
309         sess_mp = rte_mempool_from_obj(priv);
310
311         set_sec_session_private_data(sess, NULL);
312         rte_mempool_put(sess_mp, priv);
313
314         return 0;
315 }
316
317 static unsigned int
318 cn10k_sec_session_get_size(void *device __rte_unused)
319 {
320         return sizeof(struct cn10k_sec_session);
321 }
322
323 /* Update platform specific security ops */
324 void
325 cn10k_sec_ops_override(void)
326 {
327         /* Update platform specific ops */
328         cnxk_sec_ops.session_create = cn10k_sec_session_create;
329         cnxk_sec_ops.session_destroy = cn10k_sec_session_destroy;
330         cnxk_sec_ops.session_get_size = cn10k_sec_session_get_size;
331 }