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