Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2019 Marvell International Ltd.
3 : : */
4 : :
5 : : #include <rte_crypto.h>
6 : : #include <cryptodev_pmd.h>
7 : : #include <rte_cycles.h>
8 : : #include <rte_errno.h>
9 : :
10 : : #include "nitrox_sym_reqmgr.h"
11 : : #include "nitrox_logs.h"
12 : :
13 : : #define MAX_SUPPORTED_MBUF_SEGS 16
14 : : /* IV + AAD + ORH + CC + DIGEST */
15 : : #define ADDITIONAL_SGBUF_CNT 5
16 : : #define MAX_SGBUF_CNT (MAX_SUPPORTED_MBUF_SEGS + ADDITIONAL_SGBUF_CNT)
17 : : #define MAX_SGCOMP_CNT (RTE_ALIGN_MUL_CEIL(MAX_SGBUF_CNT, 4) / 4)
18 : : /* SLC_STORE_INFO */
19 : : #define MIN_UDD_LEN 16
20 : : /* PKT_IN_HDR + SLC_STORE_INFO */
21 : : #define FDATA_SIZE 32
22 : : /* Base destination port for the solicited requests */
23 : : #define SOLICIT_BASE_DPORT 256
24 : : #define PENDING_SIG 0xFFFFFFFFFFFFFFFFUL
25 : : #define CMD_TIMEOUT 2
26 : : /* For AES_CCM actual AAD will be copied 18 bytes after the AAD pointer, according to the API */
27 : : #define DPDK_AES_CCM_ADD_OFFSET 18
28 : :
29 : : struct gphdr {
30 : : uint16_t param0;
31 : : uint16_t param1;
32 : : uint16_t param2;
33 : : uint16_t param3;
34 : : };
35 : :
36 : : union pkt_instr_hdr {
37 : : uint64_t value;
38 : : struct {
39 : : #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
40 : : uint64_t raz_48_63 : 16;
41 : : uint64_t g : 1;
42 : : uint64_t gsz : 7;
43 : : uint64_t ihi : 1;
44 : : uint64_t ssz : 7;
45 : : uint64_t raz_30_31 : 2;
46 : : uint64_t fsz : 6;
47 : : uint64_t raz_16_23 : 8;
48 : : uint64_t tlen : 16;
49 : : #else
50 : : uint64_t tlen : 16;
51 : : uint64_t raz_16_23 : 8;
52 : : uint64_t fsz : 6;
53 : : uint64_t raz_30_31 : 2;
54 : : uint64_t ssz : 7;
55 : : uint64_t ihi : 1;
56 : : uint64_t gsz : 7;
57 : : uint64_t g : 1;
58 : : uint64_t raz_48_63 : 16;
59 : : #endif
60 : : } s;
61 : : };
62 : :
63 : : union pkt_hdr {
64 : : uint64_t value[2];
65 : : struct {
66 : : #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
67 : : uint64_t opcode : 8;
68 : : uint64_t arg : 8;
69 : : uint64_t ctxc : 2;
70 : : uint64_t unca : 1;
71 : : uint64_t raz_44 : 1;
72 : : uint64_t info : 3;
73 : : uint64_t destport : 9;
74 : : uint64_t unc : 8;
75 : : uint64_t raz_19_23 : 5;
76 : : uint64_t grp : 3;
77 : : uint64_t raz_15 : 1;
78 : : uint64_t ctxl : 7;
79 : : uint64_t uddl : 8;
80 : : #else
81 : : uint64_t uddl : 8;
82 : : uint64_t ctxl : 7;
83 : : uint64_t raz_15 : 1;
84 : : uint64_t grp : 3;
85 : : uint64_t raz_19_23 : 5;
86 : : uint64_t unc : 8;
87 : : uint64_t destport : 9;
88 : : uint64_t info : 3;
89 : : uint64_t raz_44 : 1;
90 : : uint64_t unca : 1;
91 : : uint64_t ctxc : 2;
92 : : uint64_t arg : 8;
93 : : uint64_t opcode : 8;
94 : : #endif
95 : : uint64_t ctxp;
96 : : } s;
97 : : };
98 : :
99 : : union slc_store_info {
100 : : uint64_t value[2];
101 : : struct {
102 : : #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
103 : : uint64_t raz_39_63 : 25;
104 : : uint64_t ssz : 7;
105 : : uint64_t raz_0_31 : 32;
106 : : #else
107 : : uint64_t raz_0_31 : 32;
108 : : uint64_t ssz : 7;
109 : : uint64_t raz_39_63 : 25;
110 : : #endif
111 : : uint64_t rptr;
112 : : } s;
113 : : };
114 : :
115 : : struct nps_pkt_instr {
116 : : uint64_t dptr0;
117 : : union pkt_instr_hdr ih;
118 : : union pkt_hdr irh;
119 : : union slc_store_info slc;
120 : : uint64_t fdata[2];
121 : : };
122 : :
123 : : struct resp_hdr {
124 : : uint64_t orh;
125 : : uint64_t completion;
126 : : };
127 : :
128 : : struct nitrox_sglist {
129 : : uint16_t len;
130 : : uint16_t raz0;
131 : : uint32_t raz1;
132 : : rte_iova_t iova;
133 : : void *virt;
134 : : };
135 : :
136 : : struct nitrox_sgcomp {
137 : : uint16_t len[4];
138 : : uint64_t iova[4];
139 : : };
140 : :
141 : : struct nitrox_sgtable {
142 : : uint8_t map_bufs_cnt;
143 : : uint8_t nr_sgcomp;
144 : : uint16_t total_bytes;
145 : :
146 : : struct nitrox_sglist sglist[MAX_SGBUF_CNT];
147 : : struct nitrox_sgcomp sgcomp[MAX_SGCOMP_CNT];
148 : : };
149 : :
150 : : struct iv {
151 : : uint8_t *virt;
152 : : rte_iova_t iova;
153 : : uint16_t len;
154 : : };
155 : :
156 : : struct nitrox_softreq {
157 : : struct nitrox_crypto_ctx *ctx;
158 : : struct rte_crypto_op *op;
159 : : struct gphdr gph;
160 : : struct nps_pkt_instr instr;
161 : : struct resp_hdr resp;
162 : : struct nitrox_sgtable in;
163 : : struct nitrox_sgtable out;
164 : : struct iv iv;
165 : : uint64_t timeout;
166 : : rte_iova_t dptr;
167 : : rte_iova_t rptr;
168 : : rte_iova_t iova;
169 : : };
170 : :
171 : : static void
172 : : softreq_init(struct nitrox_softreq *sr, rte_iova_t iova)
173 : : {
174 : : memset(sr, 0, sizeof(*sr));
175 : 0 : sr->iova = iova;
176 : : }
177 : :
178 : : /*
179 : : * 64-Byte Instruction Format
180 : : *
181 : : * ----------------------
182 : : * | DPTR0 | 8 bytes
183 : : * ----------------------
184 : : * | PKT_IN_INSTR_HDR | 8 bytes
185 : : * ----------------------
186 : : * | PKT_IN_HDR | 16 bytes
187 : : * ----------------------
188 : : * | SLC_INFO | 16 bytes
189 : : * ----------------------
190 : : * | Front data | 16 bytes
191 : : * ----------------------
192 : : */
193 : : static void
194 : 0 : create_se_instr(struct nitrox_softreq *sr, uint8_t qno)
195 : : {
196 : 0 : struct nitrox_crypto_ctx *ctx = sr->ctx;
197 : : rte_iova_t ctx_handle;
198 : :
199 : : /* fill the packet instruction */
200 : : /* word 0 */
201 [ # # ]: 0 : sr->instr.dptr0 = rte_cpu_to_be_64(sr->dptr);
202 : :
203 : : /* word 1 */
204 : 0 : sr->instr.ih.value = 0;
205 : 0 : sr->instr.ih.s.g = 1;
206 : 0 : sr->instr.ih.s.gsz = sr->in.map_bufs_cnt;
207 : 0 : sr->instr.ih.s.ssz = sr->out.map_bufs_cnt;
208 : 0 : sr->instr.ih.s.fsz = FDATA_SIZE + sizeof(struct gphdr);
209 : 0 : sr->instr.ih.s.tlen = sr->instr.ih.s.fsz + sr->in.total_bytes;
210 [ # # ]: 0 : sr->instr.ih.value = rte_cpu_to_be_64(sr->instr.ih.value);
211 : :
212 : : /* word 2 */
213 : 0 : sr->instr.irh.value[0] = 0;
214 : 0 : sr->instr.irh.s.uddl = MIN_UDD_LEN;
215 : : /* context length in 64-bit words */
216 : 0 : sr->instr.irh.s.ctxl = RTE_ALIGN_MUL_CEIL(sizeof(ctx->fctx), 8) / 8;
217 : : /* offset from solicit base port 256 */
218 : 0 : sr->instr.irh.s.destport = SOLICIT_BASE_DPORT + qno;
219 : : /* Invalid context cache */
220 : 0 : sr->instr.irh.s.ctxc = 0x3;
221 : 0 : sr->instr.irh.s.arg = ctx->req_op;
222 : 0 : sr->instr.irh.s.opcode = ctx->opcode;
223 [ # # ]: 0 : sr->instr.irh.value[0] = rte_cpu_to_be_64(sr->instr.irh.value[0]);
224 : :
225 : : /* word 3 */
226 : 0 : ctx_handle = ctx->iova + offsetof(struct nitrox_crypto_ctx, fctx);
227 [ # # ]: 0 : sr->instr.irh.s.ctxp = rte_cpu_to_be_64(ctx_handle);
228 : :
229 : : /* word 4 */
230 : 0 : sr->instr.slc.value[0] = 0;
231 : 0 : sr->instr.slc.s.ssz = sr->out.map_bufs_cnt;
232 [ # # ]: 0 : sr->instr.slc.value[0] = rte_cpu_to_be_64(sr->instr.slc.value[0]);
233 : :
234 : : /* word 5 */
235 [ # # ]: 0 : sr->instr.slc.s.rptr = rte_cpu_to_be_64(sr->rptr);
236 : : /*
237 : : * No conversion for front data,
238 : : * It goes into payload
239 : : * put GP Header in front data
240 : : */
241 : 0 : memcpy(&sr->instr.fdata[0], &sr->gph, sizeof(sr->instr.fdata[0]));
242 : 0 : sr->instr.fdata[1] = 0;
243 : 0 : }
244 : :
245 : : static void
246 : : softreq_copy_iv(struct nitrox_softreq *sr, uint8_t salt_size)
247 : : {
248 : 0 : uint16_t offset = sr->ctx->iv.offset + salt_size;
249 : :
250 : 0 : sr->iv.virt = rte_crypto_op_ctod_offset(sr->op, uint8_t *, offset);
251 : 0 : sr->iv.iova = rte_crypto_op_ctophys_offset(sr->op, offset);
252 : 0 : sr->iv.len = sr->ctx->iv.length - salt_size;
253 : 0 : }
254 : :
255 : : static void
256 : : fill_sglist(struct nitrox_sgtable *sgtbl, uint16_t len, rte_iova_t iova,
257 : : void *virt)
258 : : {
259 : 0 : struct nitrox_sglist *sglist = sgtbl->sglist;
260 : 0 : uint8_t cnt = sgtbl->map_bufs_cnt;
261 : :
262 : 0 : if (unlikely(!len))
263 : : return;
264 : :
265 : 0 : sglist[cnt].len = len;
266 : 0 : sglist[cnt].iova = iova;
267 : 0 : sglist[cnt].virt = virt;
268 : 0 : sgtbl->total_bytes += len;
269 : 0 : cnt++;
270 : 0 : sgtbl->map_bufs_cnt = cnt;
271 : : }
272 : :
273 : : static int
274 : 0 : create_sglist_from_mbuf(struct nitrox_sgtable *sgtbl, struct rte_mbuf *mbuf,
275 : : uint32_t off, int datalen)
276 : : {
277 : 0 : struct nitrox_sglist *sglist = sgtbl->sglist;
278 : 0 : uint8_t cnt = sgtbl->map_bufs_cnt;
279 : : struct rte_mbuf *m;
280 : : int mlen;
281 : :
282 [ # # ]: 0 : if (unlikely(datalen <= 0))
283 : : return 0;
284 : :
285 [ # # # # ]: 0 : for (m = mbuf; m && off > rte_pktmbuf_data_len(m); m = m->next)
286 : 0 : off -= rte_pktmbuf_data_len(m);
287 : :
288 [ # # ]: 0 : if (unlikely(!m))
289 : : return -EIO;
290 : :
291 : 0 : mlen = rte_pktmbuf_data_len(m) - off;
292 : : if (datalen <= mlen)
293 : : mlen = datalen;
294 : 0 : sglist[cnt].len = mlen;
295 : 0 : sglist[cnt].iova = rte_pktmbuf_iova_offset(m, off);
296 : 0 : sglist[cnt].virt = rte_pktmbuf_mtod_offset(m, uint8_t *, off);
297 : 0 : sgtbl->total_bytes += mlen;
298 : 0 : cnt++;
299 : 0 : datalen -= mlen;
300 [ # # ]: 0 : for (m = m->next; m && datalen; m = m->next) {
301 : 0 : mlen = rte_pktmbuf_data_len(m) < datalen ?
302 : : rte_pktmbuf_data_len(m) : datalen;
303 : 0 : sglist[cnt].len = mlen;
304 : 0 : sglist[cnt].iova = rte_pktmbuf_iova(m);
305 : 0 : sglist[cnt].virt = rte_pktmbuf_mtod(m, uint8_t *);
306 : 0 : sgtbl->total_bytes += mlen;
307 : 0 : cnt++;
308 : 0 : datalen -= mlen;
309 : : }
310 : :
311 : : RTE_ASSERT(cnt <= MAX_SGBUF_CNT);
312 : 0 : sgtbl->map_bufs_cnt = cnt;
313 : 0 : return 0;
314 : : }
315 : :
316 : : static void
317 : 0 : create_sgcomp(struct nitrox_sgtable *sgtbl)
318 : : {
319 : : int i, j, nr_sgcomp;
320 : 0 : struct nitrox_sgcomp *sgcomp = sgtbl->sgcomp;
321 : 0 : struct nitrox_sglist *sglist = sgtbl->sglist;
322 : :
323 : 0 : nr_sgcomp = RTE_ALIGN_MUL_CEIL(sgtbl->map_bufs_cnt, 4) / 4;
324 : 0 : sgtbl->nr_sgcomp = nr_sgcomp;
325 [ # # ]: 0 : for (i = 0; i < nr_sgcomp; i++, sgcomp++) {
326 [ # # ]: 0 : for (j = 0; j < 4; j++, sglist++) {
327 [ # # ]: 0 : sgcomp->len[j] = rte_cpu_to_be_16(sglist->len);
328 [ # # ]: 0 : sgcomp->iova[j] = rte_cpu_to_be_64(sglist->iova);
329 : : }
330 : : }
331 : 0 : }
332 : :
333 : : static int
334 : 0 : create_cipher_inbuf(struct nitrox_softreq *sr)
335 : : {
336 : : int err;
337 : 0 : struct rte_crypto_op *op = sr->op;
338 : :
339 [ # # ]: 0 : fill_sglist(&sr->in, sr->iv.len, sr->iv.iova, sr->iv.virt);
340 : 0 : err = create_sglist_from_mbuf(&sr->in, op->sym->m_src,
341 : : op->sym->cipher.data.offset,
342 : 0 : op->sym->cipher.data.length);
343 [ # # ]: 0 : if (unlikely(err))
344 : : return err;
345 : :
346 : 0 : create_sgcomp(&sr->in);
347 : 0 : sr->dptr = sr->iova + offsetof(struct nitrox_softreq, in.sgcomp);
348 : :
349 : 0 : return 0;
350 : : }
351 : :
352 : : static int
353 : 0 : create_cipher_outbuf(struct nitrox_softreq *sr)
354 : : {
355 : 0 : struct rte_crypto_op *op = sr->op;
356 : : int err, cnt = 0;
357 [ # # ]: 0 : struct rte_mbuf *m_dst = op->sym->m_dst ? op->sym->m_dst :
358 : : op->sym->m_src;
359 : :
360 : 0 : sr->resp.orh = PENDING_SIG;
361 : 0 : sr->out.sglist[cnt].len = sizeof(sr->resp.orh);
362 : 0 : sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq,
363 : : resp.orh);
364 : 0 : sr->out.sglist[cnt].virt = &sr->resp.orh;
365 : : cnt++;
366 : :
367 : 0 : sr->out.map_bufs_cnt = cnt;
368 [ # # ]: 0 : fill_sglist(&sr->out, sr->iv.len, sr->iv.iova, sr->iv.virt);
369 : 0 : err = create_sglist_from_mbuf(&sr->out, m_dst,
370 : : op->sym->cipher.data.offset,
371 : 0 : op->sym->cipher.data.length);
372 [ # # ]: 0 : if (unlikely(err))
373 : : return err;
374 : :
375 : 0 : cnt = sr->out.map_bufs_cnt;
376 : 0 : sr->resp.completion = PENDING_SIG;
377 : 0 : sr->out.sglist[cnt].len = sizeof(sr->resp.completion);
378 : 0 : sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq,
379 : : resp.completion);
380 : 0 : sr->out.sglist[cnt].virt = &sr->resp.completion;
381 : : cnt++;
382 : :
383 : : RTE_ASSERT(cnt <= MAX_SGBUF_CNT);
384 : 0 : sr->out.map_bufs_cnt = cnt;
385 : :
386 : 0 : create_sgcomp(&sr->out);
387 : 0 : sr->rptr = sr->iova + offsetof(struct nitrox_softreq, out.sgcomp);
388 : :
389 : 0 : return 0;
390 : : }
391 : :
392 : : static void
393 : : create_cipher_gph(uint32_t cryptlen, uint16_t ivlen, struct gphdr *gph)
394 : : {
395 : 0 : gph->param0 = rte_cpu_to_be_16(cryptlen);
396 : 0 : gph->param1 = 0;
397 [ # # ]: 0 : gph->param2 = rte_cpu_to_be_16(ivlen);
398 : 0 : gph->param3 = 0;
399 : : }
400 : :
401 : : static int
402 : 0 : process_cipher_data(struct nitrox_softreq *sr)
403 : : {
404 : 0 : struct rte_crypto_op *op = sr->op;
405 : : int err;
406 : :
407 : : softreq_copy_iv(sr, 0);
408 : 0 : err = create_cipher_inbuf(sr);
409 [ # # ]: 0 : if (unlikely(err))
410 : : return err;
411 : :
412 : 0 : err = create_cipher_outbuf(sr);
413 [ # # ]: 0 : if (unlikely(err))
414 : : return err;
415 : :
416 [ # # ]: 0 : create_cipher_gph(op->sym->cipher.data.length, sr->iv.len, &sr->gph);
417 : :
418 : 0 : return 0;
419 : : }
420 : :
421 : : static int
422 : 0 : extract_cipher_auth_digest(struct nitrox_softreq *sr,
423 : : struct nitrox_sglist *digest)
424 : : {
425 : 0 : struct rte_crypto_op *op = sr->op;
426 [ # # ]: 0 : struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst :
427 : : op->sym->m_src;
428 : :
429 [ # # ]: 0 : if (sr->ctx->req_op == NITROX_OP_DECRYPT &&
430 [ # # ]: 0 : unlikely(!op->sym->auth.digest.data))
431 : : return -EINVAL;
432 : :
433 : 0 : digest->len = sr->ctx->digest_length;
434 [ # # ]: 0 : if (op->sym->auth.digest.data) {
435 : 0 : digest->iova = op->sym->auth.digest.phys_addr;
436 : 0 : digest->virt = op->sym->auth.digest.data;
437 : 0 : return 0;
438 : : }
439 : :
440 [ # # ]: 0 : if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->auth.data.offset +
441 : : op->sym->auth.data.length + digest->len))
442 : : return -EINVAL;
443 : :
444 : 0 : digest->iova = rte_pktmbuf_iova_offset(mdst,
445 : : op->sym->auth.data.offset +
446 : : op->sym->auth.data.length);
447 : 0 : digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *,
448 : : op->sym->auth.data.offset +
449 : : op->sym->auth.data.length);
450 : 0 : return 0;
451 : : }
452 : :
453 : : static int
454 : 0 : create_cipher_auth_sglist(struct nitrox_softreq *sr,
455 : : struct nitrox_sgtable *sgtbl, struct rte_mbuf *mbuf)
456 : : {
457 : 0 : struct rte_crypto_op *op = sr->op;
458 : : int auth_only_len;
459 : : int err;
460 : :
461 [ # # ]: 0 : fill_sglist(sgtbl, sr->iv.len, sr->iv.iova, sr->iv.virt);
462 : 0 : auth_only_len = op->sym->auth.data.length - op->sym->cipher.data.length;
463 [ # # ]: 0 : if (unlikely(auth_only_len < 0))
464 : : return -EINVAL;
465 : :
466 [ # # ]: 0 : if (unlikely(
467 : : op->sym->cipher.data.offset + op->sym->cipher.data.length !=
468 : : op->sym->auth.data.offset + op->sym->auth.data.length)) {
469 : 0 : NITROX_LOG_LINE(ERR, "Auth only data after cipher data not supported");
470 : 0 : return -ENOTSUP;
471 : : }
472 : :
473 : 0 : err = create_sglist_from_mbuf(sgtbl, mbuf, op->sym->auth.data.offset,
474 : : auth_only_len);
475 [ # # ]: 0 : if (unlikely(err))
476 : : return err;
477 : :
478 : 0 : err = create_sglist_from_mbuf(sgtbl, mbuf, op->sym->cipher.data.offset,
479 : : op->sym->cipher.data.length);
480 [ # # ]: 0 : if (unlikely(err))
481 : 0 : return err;
482 : :
483 : : return 0;
484 : : }
485 : :
486 : : static int
487 : 0 : create_combined_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl,
488 : : struct rte_mbuf *mbuf)
489 : : {
490 : 0 : struct rte_crypto_op *op = sr->op;
491 : : uint32_t aad_offset = 0;
492 : :
493 [ # # ]: 0 : if (sr->ctx->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
494 : : aad_offset = DPDK_AES_CCM_ADD_OFFSET;
495 : :
496 [ # # ]: 0 : fill_sglist(sgtbl, sr->iv.len, sr->iv.iova, sr->iv.virt);
497 : 0 : fill_sglist(sgtbl, sr->ctx->aad_length,
498 : 0 : op->sym->aead.aad.phys_addr + aad_offset,
499 [ # # ]: 0 : op->sym->aead.aad.data + aad_offset);
500 : 0 : return create_sglist_from_mbuf(sgtbl, mbuf, op->sym->cipher.data.offset,
501 : 0 : op->sym->cipher.data.length);
502 : : }
503 : :
504 : : static int
505 : 0 : create_aead_sglist(struct nitrox_softreq *sr, struct nitrox_sgtable *sgtbl,
506 : : struct rte_mbuf *mbuf)
507 : : {
508 : : int err;
509 : :
510 [ # # # ]: 0 : switch (sr->ctx->nitrox_chain) {
511 : 0 : case NITROX_CHAIN_CIPHER_AUTH:
512 : : case NITROX_CHAIN_AUTH_CIPHER:
513 : 0 : err = create_cipher_auth_sglist(sr, sgtbl, mbuf);
514 : 0 : break;
515 : 0 : case NITROX_CHAIN_COMBINED:
516 : 0 : err = create_combined_sglist(sr, sgtbl, mbuf);
517 : 0 : break;
518 : : default:
519 : : err = -EINVAL;
520 : : break;
521 : : }
522 : :
523 : 0 : return err;
524 : : }
525 : :
526 : : static int
527 : 0 : create_aead_inbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
528 : : {
529 : : int err;
530 : 0 : struct nitrox_crypto_ctx *ctx = sr->ctx;
531 : :
532 : 0 : err = create_aead_sglist(sr, &sr->in, sr->op->sym->m_src);
533 [ # # ]: 0 : if (unlikely(err))
534 : : return err;
535 : :
536 [ # # ]: 0 : if (ctx->req_op == NITROX_OP_DECRYPT)
537 [ # # ]: 0 : fill_sglist(&sr->in, digest->len, digest->iova, digest->virt);
538 : :
539 : 0 : create_sgcomp(&sr->in);
540 : 0 : sr->dptr = sr->iova + offsetof(struct nitrox_softreq, in.sgcomp);
541 : 0 : return 0;
542 : : }
543 : :
544 : : static int
545 : 0 : create_aead_oop_outbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
546 : : {
547 : : int err;
548 : 0 : struct nitrox_crypto_ctx *ctx = sr->ctx;
549 : :
550 : 0 : err = create_aead_sglist(sr, &sr->out, sr->op->sym->m_dst);
551 [ # # ]: 0 : if (unlikely(err))
552 : : return err;
553 : :
554 [ # # ]: 0 : if (ctx->req_op == NITROX_OP_ENCRYPT)
555 [ # # ]: 0 : fill_sglist(&sr->out, digest->len, digest->iova, digest->virt);
556 : :
557 : : return 0;
558 : : }
559 : :
560 : : static void
561 : 0 : create_aead_inplace_outbuf(struct nitrox_softreq *sr,
562 : : struct nitrox_sglist *digest)
563 : : {
564 : : int i, cnt;
565 : 0 : struct nitrox_crypto_ctx *ctx = sr->ctx;
566 : :
567 : 0 : cnt = sr->out.map_bufs_cnt;
568 [ # # ]: 0 : for (i = 0; i < sr->in.map_bufs_cnt; i++, cnt++) {
569 : 0 : sr->out.sglist[cnt].len = sr->in.sglist[i].len;
570 : 0 : sr->out.sglist[cnt].iova = sr->in.sglist[i].iova;
571 : 0 : sr->out.sglist[cnt].virt = sr->in.sglist[i].virt;
572 : : }
573 : :
574 : 0 : sr->out.map_bufs_cnt = cnt;
575 [ # # ]: 0 : if (ctx->req_op == NITROX_OP_ENCRYPT) {
576 [ # # ]: 0 : fill_sglist(&sr->out, digest->len, digest->iova,
577 : : digest->virt);
578 [ # # ]: 0 : } else if (ctx->req_op == NITROX_OP_DECRYPT) {
579 : 0 : sr->out.map_bufs_cnt--;
580 : : }
581 : 0 : }
582 : :
583 : : static int
584 : 0 : create_aead_outbuf(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
585 : : {
586 : 0 : struct rte_crypto_op *op = sr->op;
587 : : int cnt = 0;
588 : :
589 : 0 : sr->resp.orh = PENDING_SIG;
590 : 0 : sr->out.sglist[cnt].len = sizeof(sr->resp.orh);
591 : 0 : sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq,
592 : : resp.orh);
593 : 0 : sr->out.sglist[cnt].virt = &sr->resp.orh;
594 : : cnt++;
595 : 0 : sr->out.map_bufs_cnt = cnt;
596 [ # # ]: 0 : if (op->sym->m_dst) {
597 : : int err;
598 : :
599 : 0 : err = create_aead_oop_outbuf(sr, digest);
600 [ # # ]: 0 : if (unlikely(err))
601 : : return err;
602 : : } else {
603 : 0 : create_aead_inplace_outbuf(sr, digest);
604 : : }
605 : :
606 : 0 : cnt = sr->out.map_bufs_cnt;
607 : 0 : sr->resp.completion = PENDING_SIG;
608 : 0 : sr->out.sglist[cnt].len = sizeof(sr->resp.completion);
609 : 0 : sr->out.sglist[cnt].iova = sr->iova + offsetof(struct nitrox_softreq,
610 : : resp.completion);
611 : 0 : sr->out.sglist[cnt].virt = &sr->resp.completion;
612 : : cnt++;
613 : : RTE_ASSERT(cnt <= MAX_SGBUF_CNT);
614 : 0 : sr->out.map_bufs_cnt = cnt;
615 : :
616 : 0 : create_sgcomp(&sr->out);
617 : 0 : sr->rptr = sr->iova + offsetof(struct nitrox_softreq, out.sgcomp);
618 : 0 : return 0;
619 : : }
620 : :
621 : : static void
622 : 0 : create_aead_gph(uint32_t cryptlen, uint16_t ivlen, uint32_t authlen,
623 : : struct gphdr *gph)
624 : : {
625 : : int auth_only_len;
626 : : union {
627 : : struct {
628 : : #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
629 : : uint16_t iv_offset : 8;
630 : : uint16_t auth_offset : 8;
631 : : #else
632 : : uint16_t auth_offset : 8;
633 : : uint16_t iv_offset : 8;
634 : : #endif
635 : : };
636 : : uint16_t value;
637 : : } param3;
638 : :
639 [ # # ]: 0 : gph->param0 = rte_cpu_to_be_16(cryptlen);
640 [ # # ]: 0 : gph->param1 = rte_cpu_to_be_16(authlen);
641 : :
642 : 0 : auth_only_len = authlen - cryptlen;
643 [ # # ]: 0 : gph->param2 = rte_cpu_to_be_16(ivlen + auth_only_len);
644 : :
645 : 0 : param3.iv_offset = 0;
646 : 0 : param3.auth_offset = ivlen;
647 [ # # ]: 0 : gph->param3 = rte_cpu_to_be_16(param3.value);
648 : 0 : }
649 : :
650 : : static int
651 : 0 : process_cipher_auth_data(struct nitrox_softreq *sr)
652 : : {
653 : 0 : struct rte_crypto_op *op = sr->op;
654 : : int err;
655 : : struct nitrox_sglist digest;
656 : :
657 : : softreq_copy_iv(sr, 0);
658 : 0 : err = extract_cipher_auth_digest(sr, &digest);
659 [ # # ]: 0 : if (unlikely(err))
660 : : return err;
661 : :
662 : 0 : err = create_aead_inbuf(sr, &digest);
663 [ # # ]: 0 : if (unlikely(err))
664 : : return err;
665 : :
666 : 0 : err = create_aead_outbuf(sr, &digest);
667 [ # # ]: 0 : if (unlikely(err))
668 : : return err;
669 : :
670 : 0 : create_aead_gph(op->sym->cipher.data.length, sr->iv.len,
671 : : op->sym->auth.data.length, &sr->gph);
672 : 0 : return 0;
673 : : }
674 : :
675 : : static int
676 : 0 : softreq_copy_salt(struct nitrox_softreq *sr)
677 : : {
678 : 0 : struct nitrox_crypto_ctx *ctx = sr->ctx;
679 : : uint8_t *addr;
680 : :
681 [ # # ]: 0 : if (unlikely(ctx->iv.length < AES_GCM_SALT_SIZE)) {
682 : 0 : NITROX_LOG_LINE(ERR, "Invalid IV length %d", ctx->iv.length);
683 : 0 : return -EINVAL;
684 : : }
685 : :
686 : 0 : addr = rte_crypto_op_ctod_offset(sr->op, uint8_t *, ctx->iv.offset);
687 [ # # ]: 0 : if (!memcmp(ctx->salt, addr, AES_GCM_SALT_SIZE))
688 : : return 0;
689 : :
690 : : memcpy(ctx->salt, addr, AES_GCM_SALT_SIZE);
691 : 0 : memcpy(ctx->fctx.crypto.iv, addr, AES_GCM_SALT_SIZE);
692 : 0 : return 0;
693 : : }
694 : :
695 : : static int
696 : 0 : extract_combined_digest(struct nitrox_softreq *sr, struct nitrox_sglist *digest)
697 : : {
698 : 0 : struct rte_crypto_op *op = sr->op;
699 [ # # ]: 0 : struct rte_mbuf *mdst = op->sym->m_dst ? op->sym->m_dst :
700 : : op->sym->m_src;
701 : :
702 : 0 : digest->len = sr->ctx->digest_length;
703 [ # # ]: 0 : if (op->sym->aead.digest.data) {
704 : 0 : digest->iova = op->sym->aead.digest.phys_addr;
705 : 0 : digest->virt = op->sym->aead.digest.data;
706 : :
707 : 0 : return 0;
708 : : }
709 : :
710 [ # # ]: 0 : if (unlikely(rte_pktmbuf_data_len(mdst) < op->sym->aead.data.offset +
711 : : op->sym->aead.data.length + digest->len))
712 : : return -EINVAL;
713 : :
714 : 0 : digest->iova = rte_pktmbuf_iova_offset(mdst,
715 : : op->sym->aead.data.offset +
716 : : op->sym->aead.data.length);
717 : 0 : digest->virt = rte_pktmbuf_mtod_offset(mdst, uint8_t *,
718 : : op->sym->aead.data.offset +
719 : : op->sym->aead.data.length);
720 : :
721 : 0 : return 0;
722 : : }
723 : :
724 : : static int
725 : 0 : process_combined_data(struct nitrox_softreq *sr)
726 : : {
727 : : int err;
728 : : struct nitrox_sglist digest;
729 : 0 : struct rte_crypto_op *op = sr->op;
730 : :
731 [ # # ]: 0 : if (sr->ctx->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
732 : 0 : err = softreq_copy_salt(sr);
733 [ # # ]: 0 : if (unlikely(err))
734 : : return err;
735 : :
736 : : softreq_copy_iv(sr, AES_GCM_SALT_SIZE);
737 [ # # ]: 0 : } else if (sr->ctx->aead_algo == RTE_CRYPTO_AEAD_AES_CCM) {
738 : : union {
739 : : uint8_t value;
740 : : struct {
741 : : #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
742 : : uint8_t rsvd: 1;
743 : : uint8_t adata: 1;
744 : : uint8_t mstar: 3;
745 : : uint8_t lstar: 3;
746 : : #else
747 : : uint8_t lstar: 3;
748 : : uint8_t mstar: 3;
749 : : uint8_t adata: 1;
750 : : uint8_t rsvd: 1;
751 : : #endif
752 : : };
753 : : } flags;
754 : : uint8_t L;
755 : : uint8_t *iv_addr;
756 : :
757 : 0 : flags.value = 0;
758 : : flags.rsvd = 0;
759 : 0 : flags.adata = (sr->ctx->aad_length > 0) ? 1 : 0;
760 : 0 : flags.mstar = (sr->ctx->digest_length - 2) / 2;
761 : 0 : L = 15 - sr->ctx->iv.length;
762 : 0 : flags.lstar = L - 1;
763 : 0 : iv_addr = rte_crypto_op_ctod_offset(sr->op, uint8_t *,
764 : : sr->ctx->iv.offset);
765 : : /* initialize IV flags */
766 : 0 : iv_addr[0] = flags.value;
767 : : /* initialize IV counter to 0 */
768 : 0 : memset(&iv_addr[1] + sr->ctx->iv.length, 0, L);
769 : 0 : sr->iv.virt = rte_crypto_op_ctod_offset(sr->op, uint8_t *,
770 : : sr->ctx->iv.offset);
771 : 0 : sr->iv.iova = rte_crypto_op_ctophys_offset(sr->op,
772 : : sr->ctx->iv.offset);
773 : 0 : sr->iv.len = 16;
774 : : } else {
775 : : return -EINVAL;
776 : : }
777 : :
778 : 0 : err = extract_combined_digest(sr, &digest);
779 [ # # ]: 0 : if (unlikely(err))
780 : : return err;
781 : :
782 : 0 : err = create_aead_inbuf(sr, &digest);
783 [ # # ]: 0 : if (unlikely(err))
784 : : return err;
785 : :
786 : 0 : err = create_aead_outbuf(sr, &digest);
787 [ # # ]: 0 : if (unlikely(err))
788 : : return err;
789 : :
790 : 0 : create_aead_gph(op->sym->aead.data.length, sr->iv.len,
791 : 0 : op->sym->aead.data.length + sr->ctx->aad_length,
792 : : &sr->gph);
793 : :
794 : 0 : return 0;
795 : : }
796 : :
797 : : static int
798 : 0 : process_softreq(struct nitrox_softreq *sr)
799 : : {
800 : 0 : struct nitrox_crypto_ctx *ctx = sr->ctx;
801 : : int err = 0;
802 : :
803 [ # # # # ]: 0 : switch (ctx->nitrox_chain) {
804 : 0 : case NITROX_CHAIN_CIPHER_ONLY:
805 : 0 : err = process_cipher_data(sr);
806 : 0 : break;
807 : 0 : case NITROX_CHAIN_CIPHER_AUTH:
808 : : case NITROX_CHAIN_AUTH_CIPHER:
809 : 0 : err = process_cipher_auth_data(sr);
810 : 0 : break;
811 : 0 : case NITROX_CHAIN_COMBINED:
812 : 0 : err = process_combined_data(sr);
813 : 0 : break;
814 : : default:
815 : : err = -EINVAL;
816 : : break;
817 : : }
818 : :
819 : 0 : return err;
820 : : }
821 : :
822 : : int
823 : 0 : nitrox_process_se_req(uint16_t qno, struct rte_crypto_op *op,
824 : : struct nitrox_crypto_ctx *ctx,
825 : : struct nitrox_softreq *sr)
826 : : {
827 : : int err;
828 : :
829 [ # # # # : 0 : if (unlikely(op->sym->m_src->nb_segs > MAX_SUPPORTED_MBUF_SEGS ||
# # ]
830 : : (op->sym->m_dst &&
831 : : op->sym->m_dst->nb_segs > MAX_SUPPORTED_MBUF_SEGS))) {
832 : 0 : NITROX_LOG_LINE(ERR, "Mbuf segments not supported. "
833 : : "Max supported %d", MAX_SUPPORTED_MBUF_SEGS);
834 : 0 : return -ENOTSUP;
835 : : }
836 : :
837 : 0 : softreq_init(sr, sr->iova);
838 : 0 : sr->ctx = ctx;
839 : 0 : sr->op = op;
840 : 0 : err = process_softreq(sr);
841 [ # # ]: 0 : if (unlikely(err))
842 : : return err;
843 : :
844 : 0 : create_se_instr(sr, qno);
845 : 0 : sr->timeout = rte_get_timer_cycles() + CMD_TIMEOUT * rte_get_timer_hz();
846 : 0 : return 0;
847 : : }
848 : :
849 : : int
850 : 0 : nitrox_check_se_req(struct nitrox_softreq *sr, struct rte_crypto_op **op)
851 : : {
852 : : uint64_t cc;
853 : : uint64_t orh;
854 : : int err;
855 : :
856 : 0 : cc = *(volatile uint64_t *)(&sr->resp.completion);
857 : 0 : orh = *(volatile uint64_t *)(&sr->resp.orh);
858 [ # # ]: 0 : if (cc != PENDING_SIG)
859 : 0 : err = orh & 0xff;
860 [ # # # # ]: 0 : else if ((orh != PENDING_SIG) && (orh & 0xff))
861 : 0 : err = orh & 0xff;
862 [ # # ]: 0 : else if (rte_get_timer_cycles() >= sr->timeout)
863 : : err = 0xff;
864 : : else
865 : : return -EAGAIN;
866 : :
867 [ # # ]: 0 : if (unlikely(err))
868 : 0 : NITROX_LOG_LINE(ERR, "Request err 0x%x, orh 0x%"PRIx64, err,
869 : : sr->resp.orh);
870 : :
871 : 0 : *op = sr->op;
872 : 0 : return err;
873 : : }
874 : :
875 : : void *
876 : 0 : nitrox_sym_instr_addr(struct nitrox_softreq *sr)
877 : : {
878 : 0 : return &sr->instr;
879 : : }
880 : :
881 : : static void
882 : 0 : req_pool_obj_init(__rte_unused struct rte_mempool *mp,
883 : : __rte_unused void *opaque, void *obj,
884 : : __rte_unused unsigned int obj_idx)
885 : : {
886 : : softreq_init(obj, rte_mempool_virt2iova(obj));
887 : 0 : }
888 : :
889 : : struct rte_mempool *
890 : 0 : nitrox_sym_req_pool_create(struct rte_cryptodev *cdev, uint32_t nobjs,
891 : : uint16_t qp_id, int socket_id)
892 : : {
893 : : char softreq_pool_name[RTE_RING_NAMESIZE];
894 : : struct rte_mempool *mp;
895 : :
896 : 0 : snprintf(softreq_pool_name, RTE_RING_NAMESIZE, "%s_sr_%d",
897 : 0 : cdev->data->name, qp_id);
898 : 0 : mp = rte_mempool_create(softreq_pool_name,
899 : 0 : RTE_ALIGN_MUL_CEIL(nobjs, 64),
900 : : sizeof(struct nitrox_softreq),
901 : : 64, 0, NULL, NULL, req_pool_obj_init, NULL,
902 : : socket_id, 0);
903 [ # # ]: 0 : if (unlikely(!mp))
904 : 0 : NITROX_LOG_LINE(ERR, "Failed to create req pool, qid %d, err %d",
905 : : qp_id, rte_errno);
906 : :
907 : 0 : return mp;
908 : : }
909 : :
910 : : void
911 : 0 : nitrox_sym_req_pool_free(struct rte_mempool *mp)
912 : : {
913 : 0 : rte_mempool_free(mp);
914 : 0 : }
|