Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <cryptodev_pmd.h>
6 : : #include <rte_ip.h>
7 : : #include <rte_security.h>
8 : : #include <rte_security_driver.h>
9 : :
10 : : #include "cnxk_cryptodev.h"
11 : : #include "cnxk_cryptodev_ops.h"
12 : : #include "cnxk_ipsec.h"
13 : : #include "cnxk_security.h"
14 : : #include "cn9k_ipsec.h"
15 : :
16 : : #include "roc_api.h"
17 : :
18 : : static int
19 : 0 : cn9k_ipsec_outb_sa_create(struct cnxk_cpt_qp *qp,
20 : : struct rte_security_ipsec_xform *ipsec,
21 : : struct rte_crypto_sym_xform *crypto_xform,
22 : : struct rte_security_session *sec_sess)
23 : : {
24 : 0 : struct roc_cpt *roc_cpt = qp->lf.roc_cpt;
25 : : union roc_on_ipsec_outb_param1 param1;
26 : : struct cnxk_cpt_inst_tmpl *inst_tmpl;
27 : : struct cn9k_sec_session *sess;
28 : : struct cn9k_ipsec_sa *sa;
29 : : union cpt_inst_w4 w4;
30 : : union cpt_inst_w7 w7;
31 : : size_t ctx_len;
32 : : uint8_t egrp;
33 : : int ret;
34 : :
35 : : sess = (struct cn9k_sec_session *)sec_sess;
36 [ # # ]: 0 : sa = &sess->sa;
37 : :
38 : : /* Initialize lookaside IPsec private data */
39 : :
40 : : memset(sa, 0, sizeof(struct cn9k_ipsec_sa));
41 : :
42 : 0 : sess->is_outbound = 1;
43 : :
44 [ # # ]: 0 : if (ipsec->esn.value)
45 : 0 : sess->esn = ipsec->esn.value - 1;
46 : :
47 : 0 : ret = cnxk_ipsec_outb_rlens_get(&sess->rlens, ipsec, crypto_xform);
48 [ # # ]: 0 : if (ret)
49 : : return ret;
50 : :
51 : 0 : sess->custom_hdr_len =
52 : : sizeof(struct roc_ie_on_outb_hdr) - ROC_IE_ON_MAX_IV_LEN;
53 : :
54 : : #ifdef LA_IPSEC_DEBUG
55 : : /* Use IV from application in debug mode */
56 : : if (ipsec->options.iv_gen_disable == 1) {
57 : : sess->custom_hdr_len = sizeof(struct roc_ie_on_outb_hdr);
58 : :
59 : : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
60 : : sess->cipher_iv_off = crypto_xform->aead.iv.offset;
61 : : sess->cipher_iv_len = crypto_xform->aead.iv.length;
62 : : } else if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
63 : : sess->cipher_iv_off = crypto_xform->cipher.iv.offset;
64 : : sess->cipher_iv_len = crypto_xform->cipher.iv.length;
65 : : } else {
66 : : sess->cipher_iv_off = crypto_xform->auth.iv.offset;
67 : : sess->cipher_iv_len = crypto_xform->auth.iv.length;
68 : : }
69 : : }
70 : : #else
71 [ # # ]: 0 : if (ipsec->options.iv_gen_disable != 0) {
72 : 0 : plt_err("Application provided IV is not supported");
73 : 0 : return -ENOTSUP;
74 : : }
75 : : #endif
76 : :
77 : 0 : ret = cnxk_on_ipsec_outb_sa_create(ipsec, crypto_xform, &sa->out_sa);
78 : :
79 [ # # ]: 0 : if (ret < 0)
80 : : return ret;
81 : :
82 : 0 : ctx_len = ret;
83 : 0 : egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_IE];
84 : :
85 : 0 : w4.u64 = 0;
86 : 0 : w4.s.opcode_major = ROC_IE_ON_MAJOR_OP_PROCESS_OUTBOUND_IPSEC | ROC_IE_ON_INPLACE_BIT;
87 : 0 : w4.s.opcode_minor = ctx_len >> 3;
88 : :
89 : : param1.u16 = 0;
90 : : param1.s.ikev2 = 1;
91 : :
92 : : #ifdef LA_IPSEC_DEBUG
93 : : /* Use IV from application in debug mode */
94 : : if (ipsec->options.iv_gen_disable == 1)
95 : : param1.s.per_pkt_iv = ROC_IE_ON_IV_SRC_FROM_DPTR;
96 : : #else
97 [ # # ]: 0 : if (ipsec->options.iv_gen_disable != 0) {
98 : 0 : plt_err("Application provided IV is not supported");
99 : 0 : return -ENOTSUP;
100 : : }
101 : : #endif
102 : :
103 : 0 : w4.s.param1 = param1.u16;
104 : :
105 : 0 : w7.u64 = 0;
106 : 0 : w7.s.egrp = egrp;
107 : 0 : w7.s.cptr = (uintptr_t)&sess->sa;
108 : :
109 : : inst_tmpl = &sess->inst;
110 : 0 : inst_tmpl->w4 = w4.u64;
111 : 0 : inst_tmpl->w7 = w7.u64;
112 : :
113 : 0 : return 0;
114 : : }
115 : :
116 : : static int
117 : 0 : cn9k_ipsec_inb_sa_create(struct cnxk_cpt_qp *qp,
118 : : struct rte_security_ipsec_xform *ipsec,
119 : : struct rte_crypto_sym_xform *crypto_xform,
120 : : struct rte_security_session *sec_sess)
121 : : {
122 : 0 : struct roc_cpt *roc_cpt = qp->lf.roc_cpt;
123 : : struct cnxk_cpt_inst_tmpl *inst_tmpl;
124 : : union roc_on_ipsec_inb_param2 param2;
125 : : struct cn9k_sec_session *sess;
126 : : struct cn9k_ipsec_sa *sa;
127 : : union cpt_inst_w4 w4;
128 : : union cpt_inst_w7 w7;
129 : : size_t ctx_len = 0;
130 : : uint8_t egrp;
131 : : int ret = 0;
132 : :
133 : : sess = (struct cn9k_sec_session *)sec_sess;
134 [ # # ]: 0 : sa = &sess->sa;
135 : :
136 : : memset(sa, 0, sizeof(struct cn9k_ipsec_sa));
137 : :
138 : 0 : sess->is_outbound = 0;
139 : 0 : sess->replay_win_sz = ipsec->replay_win_sz;
140 : :
141 [ # # ]: 0 : if (sess->replay_win_sz) {
142 [ # # ]: 0 : if (sess->replay_win_sz > CNXK_ON_AR_WIN_SIZE_MAX) {
143 : 0 : plt_err("Replay window size:%u is not supported", sess->replay_win_sz);
144 : 0 : return -ENOTSUP;
145 : : }
146 : :
147 : : /* Set window bottom to 1, base and top to size of window */
148 : 0 : sess->ar.winb = 1;
149 : 0 : sess->ar.wint = sess->replay_win_sz;
150 : 0 : sess->ar.base = sess->replay_win_sz;
151 : :
152 : 0 : sess->seq_lo = ipsec->esn.low;
153 : 0 : sess->seq_hi = ipsec->esn.hi;
154 : :
155 : 0 : sess->sa.in_sa.common_sa.seq_t.tl = sess->seq_lo;
156 : 0 : sess->sa.in_sa.common_sa.seq_t.th = sess->seq_hi;
157 : : }
158 : :
159 : 0 : ret = cnxk_on_ipsec_inb_sa_create(ipsec, crypto_xform, &sa->in_sa);
160 [ # # ]: 0 : if (ret < 0)
161 : : return ret;
162 : :
163 [ # # ]: 0 : if (sa->in_sa.common_sa.ctl.esn_en)
164 : 0 : sess->esn_en = 1;
165 : :
166 : 0 : ctx_len = ret;
167 : 0 : egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_IE];
168 : :
169 : 0 : w4.u64 = 0;
170 : 0 : w4.s.opcode_major = ROC_IE_ON_MAJOR_OP_PROCESS_INBOUND_IPSEC | ROC_IE_ON_INPLACE_BIT;
171 : 0 : w4.s.opcode_minor = ctx_len >> 3;
172 : :
173 : : param2.u16 = 0;
174 : : param2.s.ikev2 = 1;
175 : 0 : w4.s.param2 = param2.u16;
176 : :
177 : 0 : w7.s.egrp = egrp;
178 : 0 : w7.s.cptr = (uintptr_t)&sess->sa;
179 : :
180 : : inst_tmpl = &sess->inst;
181 : 0 : inst_tmpl->w4 = w4.u64;
182 : 0 : inst_tmpl->w7 = w7.u64;
183 : :
184 : 0 : return 0;
185 : : }
186 : :
187 : : static inline int
188 : 0 : cn9k_ipsec_xform_verify(struct rte_security_ipsec_xform *ipsec,
189 : : struct rte_crypto_sym_xform *crypto)
190 : : {
191 [ # # ]: 0 : if (ipsec->life.bytes_hard_limit != 0 ||
192 [ # # ]: 0 : ipsec->life.bytes_soft_limit != 0 ||
193 [ # # ]: 0 : ipsec->life.packets_hard_limit != 0 ||
194 [ # # ]: 0 : ipsec->life.packets_soft_limit != 0)
195 : : return -ENOTSUP;
196 : :
197 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT &&
198 [ # # ]: 0 : ipsec->proto != RTE_SECURITY_IPSEC_SA_PROTO_AH) {
199 : 0 : enum rte_crypto_sym_xform_type type = crypto->type;
200 : :
201 [ # # ]: 0 : if (type == RTE_CRYPTO_SYM_XFORM_AEAD) {
202 [ # # ]: 0 : if ((crypto->aead.algo == RTE_CRYPTO_AEAD_AES_GCM) &&
203 [ # # ]: 0 : (crypto->aead.key.length == 32)) {
204 : 0 : plt_err("Transport mode AES-256-GCM is not supported");
205 : 0 : return -ENOTSUP;
206 : : }
207 : : }
208 : : }
209 : : return 0;
210 : : }
211 : :
212 : : static int
213 : 0 : cn9k_ipsec_session_create(void *dev,
214 : : struct rte_security_ipsec_xform *ipsec_xform,
215 : : struct rte_crypto_sym_xform *crypto_xform,
216 : : struct rte_security_session *sess)
217 : : {
218 : : struct rte_cryptodev *crypto_dev = dev;
219 : : struct cnxk_cpt_qp *qp;
220 : : int ret;
221 : :
222 : 0 : qp = crypto_dev->data->queue_pairs[0];
223 [ # # ]: 0 : if (qp == NULL) {
224 : 0 : plt_err("CPT queue pairs need to be setup for creating security"
225 : : " session");
226 : 0 : return -EPERM;
227 : : }
228 : :
229 : 0 : ret = cnxk_ipsec_xform_verify(ipsec_xform, crypto_xform);
230 [ # # ]: 0 : if (ret)
231 : : return ret;
232 : :
233 : 0 : ret = cn9k_ipsec_xform_verify(ipsec_xform, crypto_xform);
234 [ # # ]: 0 : if (ret)
235 : : return ret;
236 : :
237 [ # # ]: 0 : if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
238 : 0 : return cn9k_ipsec_inb_sa_create(qp, ipsec_xform, crypto_xform,
239 : : sess);
240 : : else
241 : 0 : return cn9k_ipsec_outb_sa_create(qp, ipsec_xform, crypto_xform,
242 : : sess);
243 : : }
244 : :
245 : : static int
246 : 0 : cn9k_sec_session_create(void *device, struct rte_security_session_conf *conf,
247 : : struct rte_security_session *sess)
248 : : {
249 : 0 : struct cn9k_sec_session *priv = SECURITY_GET_SESS_PRIV(sess);
250 : :
251 [ # # ]: 0 : if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
252 : : return -EINVAL;
253 : :
254 : : memset(priv, 0, sizeof(*priv));
255 : :
256 [ # # ]: 0 : if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC)
257 : : return -ENOTSUP;
258 : :
259 : 0 : return cn9k_ipsec_session_create(device, &conf->ipsec,
260 : : conf->crypto_xform, sess);
261 : : }
262 : :
263 : : static int
264 : 0 : cn9k_sec_session_destroy(void *device __rte_unused,
265 : : struct rte_security_session *sess)
266 : : {
267 : : struct roc_ie_on_outb_sa *out_sa;
268 : : struct cn9k_sec_session *priv;
269 : : struct roc_ie_on_sa_ctl *ctl;
270 : : struct cn9k_ipsec_sa *sa;
271 : :
272 : 0 : priv = SECURITY_GET_SESS_PRIV(sess);
273 : : if (priv == NULL)
274 : : return 0;
275 : :
276 : : sa = &priv->sa;
277 : : out_sa = &sa->out_sa;
278 : :
279 : : ctl = &out_sa->common_sa.ctl;
280 : 0 : ctl->valid = 0;
281 : :
282 : 0 : rte_io_wmb();
283 : :
284 : : memset(priv, 0, sizeof(*priv));
285 : :
286 : : return 0;
287 : : }
288 : :
289 : : static unsigned int
290 : 0 : cn9k_sec_session_get_size(void *device __rte_unused)
291 : : {
292 : 0 : return sizeof(struct cn9k_sec_session);
293 : : }
294 : :
295 : : static int
296 : 0 : cn9k_sec_session_update(void *device, struct rte_security_session *sec_sess,
297 : : struct rte_security_session_conf *conf)
298 : : {
299 : : struct rte_cryptodev *crypto_dev = device;
300 : : struct cnxk_cpt_qp *qp;
301 : : int ret;
302 : :
303 : 0 : qp = crypto_dev->data->queue_pairs[0];
304 [ # # ]: 0 : if (qp == NULL) {
305 : 0 : plt_err("CPT queue pairs need to be setup for updating security"
306 : : " session");
307 : 0 : return -EPERM;
308 : : }
309 : :
310 [ # # ]: 0 : if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
311 : : return -ENOTSUP;
312 : :
313 : 0 : ret = cnxk_ipsec_xform_verify(&conf->ipsec, conf->crypto_xform);
314 [ # # ]: 0 : if (ret)
315 : : return ret;
316 : :
317 : 0 : ret = cn9k_ipsec_xform_verify(&conf->ipsec, conf->crypto_xform);
318 [ # # ]: 0 : if (ret)
319 : : return ret;
320 : :
321 : 0 : return cn9k_ipsec_outb_sa_create(qp, &conf->ipsec, conf->crypto_xform,
322 : : sec_sess);
323 : : }
324 : :
325 : : /* Update platform specific security ops */
326 : : void
327 : 0 : cn9k_sec_ops_override(void)
328 : : {
329 : : /* Update platform specific ops */
330 : 0 : cnxk_sec_ops.session_create = cn9k_sec_session_create;
331 : 0 : cnxk_sec_ops.session_destroy = cn9k_sec_session_destroy;
332 : 0 : cnxk_sec_ops.session_get_size = cn9k_sec_session_get_size;
333 : 0 : cnxk_sec_ops.session_update = cn9k_sec_session_update;
334 : 0 : }
|