crypto/cnxk: support lookaside IPsec AES-CBC-HMAC-SHA256
[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 <cryptodev_pmd.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 uint64_t
21 ipsec_cpt_inst_w7_get(struct roc_cpt *roc_cpt, void *sa)
22 {
23         union cpt_inst_w7 w7;
24
25         w7.u64 = 0;
26         w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_IE];
27         w7.s.ctx_val = 1;
28         w7.s.cptr = (uint64_t)sa;
29         rte_mb();
30
31         return w7.u64;
32 }
33
34 static int
35 cn10k_ipsec_outb_sa_create(struct roc_cpt *roc_cpt,
36                            struct rte_security_ipsec_xform *ipsec_xfrm,
37                            struct rte_crypto_sym_xform *crypto_xfrm,
38                            struct rte_security_session *sec_sess)
39 {
40         union roc_ot_ipsec_outb_param1 param1;
41         struct roc_ot_ipsec_outb_sa *out_sa;
42         struct cnxk_ipsec_outb_rlens rlens;
43         struct cn10k_sec_session *sess;
44         struct cn10k_ipsec_sa *sa;
45         union cpt_inst_w4 inst_w4;
46         int ret;
47
48         sess = get_sec_session_private_data(sec_sess);
49         sa = &sess->sa;
50         out_sa = &sa->out_sa;
51
52         memset(out_sa, 0, sizeof(struct roc_ot_ipsec_outb_sa));
53
54         /* Translate security parameters to SA */
55         ret = cnxk_ot_ipsec_outb_sa_fill(out_sa, ipsec_xfrm, crypto_xfrm);
56         if (ret)
57                 return ret;
58
59         sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
60
61 #ifdef LA_IPSEC_DEBUG
62         /* Use IV from application in debug mode */
63         if (ipsec_xfrm->options.iv_gen_disable == 1) {
64                 out_sa->w2.s.iv_src = ROC_IE_OT_SA_IV_SRC_FROM_SA;
65                 if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
66                         sa->iv_offset = crypto_xfrm->aead.iv.offset;
67                         sa->iv_length = crypto_xfrm->aead.iv.length;
68                 } else {
69                         sa->iv_offset = crypto_xfrm->cipher.iv.offset;
70                         sa->iv_length = crypto_xfrm->cipher.iv.length;
71                 }
72         }
73 #else
74         if (ipsec_xfrm->options.iv_gen_disable != 0) {
75                 plt_err("Application provided IV not supported");
76                 return -ENOTSUP;
77         }
78 #endif
79
80         /* Get Rlen calculation data */
81         ret = cnxk_ipsec_outb_rlens_get(&rlens, ipsec_xfrm, crypto_xfrm);
82         if (ret)
83                 return ret;
84
85         sa->max_extended_len = rlens.max_extended_len;
86
87         /* pre-populate CPT INST word 4 */
88         inst_w4.u64 = 0;
89         inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC;
90
91         param1.u16 = 0;
92
93         /* Disable IP checksum computation by default */
94         param1.s.ip_csum_disable = ROC_IE_OT_SA_INNER_PKT_IP_CSUM_DISABLE;
95
96         if (ipsec_xfrm->options.ip_csum_enable) {
97                 param1.s.ip_csum_disable =
98                         ROC_IE_OT_SA_INNER_PKT_IP_CSUM_ENABLE;
99         }
100
101         /* Disable L4 checksum computation by default */
102         param1.s.l4_csum_disable = ROC_IE_OT_SA_INNER_PKT_L4_CSUM_DISABLE;
103
104         if (ipsec_xfrm->options.l4_csum_enable) {
105                 param1.s.l4_csum_disable =
106                         ROC_IE_OT_SA_INNER_PKT_L4_CSUM_ENABLE;
107         }
108
109         inst_w4.s.param1 = param1.u16;
110
111         sa->inst.w4 = inst_w4.u64;
112
113         return 0;
114 }
115
116 static int
117 cn10k_ipsec_inb_sa_create(struct roc_cpt *roc_cpt,
118                           struct rte_security_ipsec_xform *ipsec_xfrm,
119                           struct rte_crypto_sym_xform *crypto_xfrm,
120                           struct rte_security_session *sec_sess)
121 {
122         union roc_ot_ipsec_inb_param1 param1;
123         struct roc_ot_ipsec_inb_sa *in_sa;
124         struct cn10k_sec_session *sess;
125         struct cn10k_ipsec_sa *sa;
126         union cpt_inst_w4 inst_w4;
127         int ret;
128
129         sess = get_sec_session_private_data(sec_sess);
130         sa = &sess->sa;
131         in_sa = &sa->in_sa;
132
133         /* Translate security parameters to SA */
134         ret = cnxk_ot_ipsec_inb_sa_fill(in_sa, ipsec_xfrm, crypto_xfrm);
135         if (ret)
136                 return ret;
137
138         /* TODO add support for antireplay */
139         sa->in_sa.w0.s.ar_win = 0;
140
141         /* TODO add support for udp encap */
142
143         sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
144
145         /* pre-populate CPT INST word 4 */
146         inst_w4.u64 = 0;
147         inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_INBOUND_IPSEC;
148
149         param1.u16 = 0;
150
151         /* Disable IP checksum verification by default */
152         param1.s.ip_csum_disable = ROC_IE_OT_SA_INNER_PKT_IP_CSUM_DISABLE;
153
154         if (ipsec_xfrm->options.ip_csum_enable) {
155                 param1.s.ip_csum_disable =
156                         ROC_IE_OT_SA_INNER_PKT_IP_CSUM_ENABLE;
157                 sa->ip_csum_enable = true;
158         }
159
160         /* Disable L4 checksum verification by default */
161         param1.s.l4_csum_disable = ROC_IE_OT_SA_INNER_PKT_L4_CSUM_DISABLE;
162
163         if (ipsec_xfrm->options.l4_csum_enable) {
164                 param1.s.l4_csum_disable =
165                         ROC_IE_OT_SA_INNER_PKT_L4_CSUM_ENABLE;
166         }
167
168         param1.s.esp_trailer_disable = 1;
169
170         inst_w4.s.param1 = param1.u16;
171
172         sa->inst.w4 = inst_w4.u64;
173
174         return 0;
175 }
176
177 static int
178 cn10k_ipsec_session_create(void *dev,
179                            struct rte_security_ipsec_xform *ipsec_xfrm,
180                            struct rte_crypto_sym_xform *crypto_xfrm,
181                            struct rte_security_session *sess)
182 {
183         struct rte_cryptodev *crypto_dev = dev;
184         struct roc_cpt *roc_cpt;
185         struct cnxk_cpt_vf *vf;
186         int ret;
187
188         vf = crypto_dev->data->dev_private;
189         roc_cpt = &vf->cpt;
190
191         if (crypto_dev->data->queue_pairs[0] == NULL) {
192                 plt_err("Setup cpt queue pair before creating security session");
193                 return -EPERM;
194         }
195
196         ret = cnxk_ipsec_xform_verify(ipsec_xfrm, crypto_xfrm);
197         if (ret)
198                 return ret;
199
200         if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
201                 return cn10k_ipsec_inb_sa_create(roc_cpt, ipsec_xfrm,
202                                                  crypto_xfrm, sess);
203         else
204                 return cn10k_ipsec_outb_sa_create(roc_cpt, ipsec_xfrm,
205                                                   crypto_xfrm, sess);
206 }
207
208 static int
209 cn10k_sec_session_create(void *device, struct rte_security_session_conf *conf,
210                          struct rte_security_session *sess,
211                          struct rte_mempool *mempool)
212 {
213         struct cn10k_sec_session *priv;
214         int ret;
215
216         if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
217                 return -EINVAL;
218
219         if (rte_mempool_get(mempool, (void **)&priv)) {
220                 plt_err("Could not allocate security session private data");
221                 return -ENOMEM;
222         }
223
224         set_sec_session_private_data(sess, priv);
225
226         if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
227                 ret = -ENOTSUP;
228                 goto mempool_put;
229         }
230         ret = cn10k_ipsec_session_create(device, &conf->ipsec,
231                                          conf->crypto_xform, sess);
232         if (ret)
233                 goto mempool_put;
234
235         return 0;
236
237 mempool_put:
238         rte_mempool_put(mempool, priv);
239         set_sec_session_private_data(sess, NULL);
240         return ret;
241 }
242
243 static int
244 cn10k_sec_session_destroy(void *device __rte_unused,
245                           struct rte_security_session *sess)
246 {
247         struct cn10k_sec_session *priv;
248         struct rte_mempool *sess_mp;
249
250         priv = get_sec_session_private_data(sess);
251
252         if (priv == NULL)
253                 return 0;
254
255         sess_mp = rte_mempool_from_obj(priv);
256
257         set_sec_session_private_data(sess, NULL);
258         rte_mempool_put(sess_mp, priv);
259
260         return 0;
261 }
262
263 static unsigned int
264 cn10k_sec_session_get_size(void *device __rte_unused)
265 {
266         return sizeof(struct cn10k_sec_session);
267 }
268
269 /* Update platform specific security ops */
270 void
271 cn10k_sec_ops_override(void)
272 {
273         /* Update platform specific ops */
274         cnxk_sec_ops.session_create = cn10k_sec_session_create;
275         cnxk_sec_ops.session_destroy = cn10k_sec_session_destroy;
276         cnxk_sec_ops.session_get_size = cn10k_sec_session_get_size;
277 }