1
2
3
4
5#include "pmd_chacha_poly_priv.h"
6
7
8static int
9chacha20_poly1305_session_configure(IMB_MGR * mb_mgr __rte_unused,
10 void *priv_sess, const struct rte_crypto_sym_xform *xform)
11{
12 struct chacha20_poly1305_session *sess = priv_sess;
13 const struct rte_crypto_sym_xform *auth_xform;
14 const struct rte_crypto_sym_xform *cipher_xform;
15 const struct rte_crypto_sym_xform *aead_xform;
16
17 uint8_t key_length;
18 const uint8_t *key;
19 enum ipsec_mb_operation mode;
20 int ret = 0;
21
22 ret = ipsec_mb_parse_xform(xform, &mode, &auth_xform,
23 &cipher_xform, &aead_xform);
24 if (ret)
25 return ret;
26
27 sess->op = mode;
28
29 switch (sess->op) {
30 case IPSEC_MB_OP_AEAD_AUTHENTICATED_ENCRYPT:
31 case IPSEC_MB_OP_AEAD_AUTHENTICATED_DECRYPT:
32 if (aead_xform->aead.algo !=
33 RTE_CRYPTO_AEAD_CHACHA20_POLY1305) {
34 IPSEC_MB_LOG(ERR,
35 "The only combined operation supported is CHACHA20 POLY1305");
36 ret = -ENOTSUP;
37 goto error_exit;
38 }
39
40 sess->iv.offset = aead_xform->aead.iv.offset;
41 sess->iv.length = aead_xform->aead.iv.length;
42 key_length = aead_xform->aead.key.length;
43 key = aead_xform->aead.key.data;
44 sess->aad_length = aead_xform->aead.aad_length;
45 sess->req_digest_length = aead_xform->aead.digest_length;
46 break;
47 default:
48 IPSEC_MB_LOG(
49 ERR, "Wrong xform type, has to be AEAD or authentication");
50 ret = -ENOTSUP;
51 goto error_exit;
52 }
53
54
55 if (sess->iv.length != CHACHA20_POLY1305_IV_LENGTH &&
56 sess->iv.length != 0) {
57 IPSEC_MB_LOG(ERR, "Wrong IV length");
58 ret = -EINVAL;
59 goto error_exit;
60 }
61
62
63 if (key_length != CHACHA20_POLY1305_KEY_SIZE) {
64 IPSEC_MB_LOG(ERR, "Invalid key length");
65 ret = -EINVAL;
66 goto error_exit;
67 } else {
68 memcpy(sess->key, key, CHACHA20_POLY1305_KEY_SIZE);
69 }
70
71
72 if (sess->req_digest_length != CHACHA20_POLY1305_DIGEST_LENGTH) {
73 IPSEC_MB_LOG(ERR, "Invalid digest length");
74 ret = -EINVAL;
75 goto error_exit;
76 } else {
77 sess->gen_digest_length = CHACHA20_POLY1305_DIGEST_LENGTH;
78 }
79
80error_exit:
81 return ret;
82}
83
84
85
86
87
88
89
90
91
92
93
94
95static int
96chacha20_poly1305_crypto_op(struct ipsec_mb_qp *qp, struct rte_crypto_op *op,
97 struct chacha20_poly1305_session *session)
98{
99 struct chacha20_poly1305_qp_data *qp_data =
100 ipsec_mb_get_qp_private_data(qp);
101 uint8_t *src, *dst;
102 uint8_t *iv_ptr;
103 struct rte_crypto_sym_op *sym_op = op->sym;
104 struct rte_mbuf *m_src = sym_op->m_src;
105 uint32_t offset, data_offset, data_length;
106 uint32_t part_len, data_len;
107 int total_len;
108 uint8_t *tag;
109 unsigned int oop = 0;
110
111 offset = sym_op->aead.data.offset;
112 data_offset = offset;
113 data_length = sym_op->aead.data.length;
114 RTE_ASSERT(m_src != NULL);
115
116 while (offset >= m_src->data_len && data_length != 0) {
117 offset -= m_src->data_len;
118 m_src = m_src->next;
119
120 RTE_ASSERT(m_src != NULL);
121 }
122
123 src = rte_pktmbuf_mtod_offset(m_src, uint8_t *, offset);
124
125 data_len = m_src->data_len - offset;
126 part_len = (data_len < data_length) ? data_len :
127 data_length;
128
129
130 if (sym_op->m_dst == NULL || (sym_op->m_dst == sym_op->m_src))
131 dst = src;
132
133 else {
134 oop = 1;
135
136
137
138 RTE_ASSERT(rte_pktmbuf_is_contiguous(sym_op->m_dst));
139 dst = rte_pktmbuf_mtod_offset(sym_op->m_dst, uint8_t *,
140 data_offset);
141 }
142
143 iv_ptr = rte_crypto_op_ctod_offset(op, uint8_t *,
144 session->iv.offset);
145
146 IMB_CHACHA20_POLY1305_INIT(qp->mb_mgr, session->key,
147 &qp_data->chacha20_poly1305_ctx_data,
148 iv_ptr, sym_op->aead.aad.data,
149 (uint64_t)session->aad_length);
150
151 if (session->op == IPSEC_MB_OP_AEAD_AUTHENTICATED_ENCRYPT) {
152 IMB_CHACHA20_POLY1305_ENC_UPDATE(qp->mb_mgr,
153 session->key,
154 &qp_data->chacha20_poly1305_ctx_data,
155 dst, src, (uint64_t)part_len);
156 total_len = data_length - part_len;
157
158 while (total_len) {
159 m_src = m_src->next;
160 RTE_ASSERT(m_src != NULL);
161
162 src = rte_pktmbuf_mtod(m_src, uint8_t *);
163 if (oop)
164 dst += part_len;
165 else
166 dst = src;
167 part_len = (m_src->data_len < total_len) ?
168 m_src->data_len : total_len;
169
170 if (dst == NULL || src == NULL) {
171 IPSEC_MB_LOG(ERR, "Invalid src or dst input");
172 return -EINVAL;
173 }
174 IMB_CHACHA20_POLY1305_ENC_UPDATE(qp->mb_mgr,
175 session->key,
176 &qp_data->chacha20_poly1305_ctx_data,
177 dst, src, (uint64_t)part_len);
178 total_len -= part_len;
179 if (total_len < 0) {
180 IPSEC_MB_LOG(ERR, "Invalid part len");
181 return -EINVAL;
182 }
183 }
184
185 tag = sym_op->aead.digest.data;
186 IMB_CHACHA20_POLY1305_ENC_FINALIZE(qp->mb_mgr,
187 &qp_data->chacha20_poly1305_ctx_data,
188 tag, session->gen_digest_length);
189
190 } else {
191 IMB_CHACHA20_POLY1305_DEC_UPDATE(qp->mb_mgr,
192 session->key,
193 &qp_data->chacha20_poly1305_ctx_data,
194 dst, src, (uint64_t)part_len);
195
196 total_len = data_length - part_len;
197
198 while (total_len) {
199 m_src = m_src->next;
200
201 RTE_ASSERT(m_src != NULL);
202
203 src = rte_pktmbuf_mtod(m_src, uint8_t *);
204 if (oop)
205 dst += part_len;
206 else
207 dst = src;
208 part_len = (m_src->data_len < total_len) ?
209 m_src->data_len : total_len;
210
211 if (dst == NULL || src == NULL) {
212 IPSEC_MB_LOG(ERR, "Invalid src or dst input");
213 return -EINVAL;
214 }
215 IMB_CHACHA20_POLY1305_DEC_UPDATE(qp->mb_mgr,
216 session->key,
217 &qp_data->chacha20_poly1305_ctx_data,
218 dst, src, (uint64_t)part_len);
219 total_len -= part_len;
220 if (total_len < 0) {
221 IPSEC_MB_LOG(ERR, "Invalid part len");
222 return -EINVAL;
223 }
224 }
225
226 tag = qp_data->temp_digest;
227 IMB_CHACHA20_POLY1305_DEC_FINALIZE(qp->mb_mgr,
228 &qp_data->chacha20_poly1305_ctx_data,
229 tag, session->gen_digest_length);
230 }
231
232 return 0;
233}
234
235
236
237
238
239
240
241
242
243
244
245static void
246post_process_chacha20_poly1305_crypto_op(struct ipsec_mb_qp *qp,
247 struct rte_crypto_op *op,
248 struct chacha20_poly1305_session *session)
249{
250 struct chacha20_poly1305_qp_data *qp_data =
251 ipsec_mb_get_qp_private_data(qp);
252
253 op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
254
255 if (session->op == IPSEC_MB_OP_AEAD_AUTHENTICATED_DECRYPT ||
256 session->op == IPSEC_MB_OP_HASH_VERIFY_ONLY) {
257 uint8_t *digest = op->sym->aead.digest.data;
258 uint8_t *tag = qp_data->temp_digest;
259
260#ifdef RTE_LIBRTE_PMD_CHACHA20_POLY1305_DEBUG
261 rte_hexdump(stdout, "auth tag (orig):",
262 digest, session->req_digest_length);
263 rte_hexdump(stdout, "auth tag (calc):",
264 tag, session->req_digest_length);
265#endif
266 if (memcmp(tag, digest, session->req_digest_length) != 0)
267 op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
268
269 }
270
271}
272
273
274
275
276
277
278
279
280
281
282
283static void
284handle_completed_chacha20_poly1305_crypto_op(struct ipsec_mb_qp *qp,
285 struct rte_crypto_op *op,
286 struct chacha20_poly1305_session *sess)
287{
288 post_process_chacha20_poly1305_crypto_op(qp, op, sess);
289
290
291 if (op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) {
292 memset(sess, 0, sizeof(struct chacha20_poly1305_session));
293 rte_mempool_put(qp->sess_mp, op->sym->session);
294 op->sym->session = NULL;
295 }
296}
297
298static uint16_t
299chacha20_poly1305_pmd_dequeue_burst(void *queue_pair,
300 struct rte_crypto_op **ops, uint16_t nb_ops)
301{
302 struct chacha20_poly1305_session *sess;
303 struct ipsec_mb_qp *qp = queue_pair;
304
305 int retval = 0;
306 unsigned int i = 0, nb_dequeued;
307
308 nb_dequeued = rte_ring_dequeue_burst(qp->ingress_queue,
309 (void **)ops, nb_ops, NULL);
310
311 for (i = 0; i < nb_dequeued; i++) {
312
313 sess = ipsec_mb_get_session_private(qp, ops[i]);
314 if (unlikely(sess == NULL)) {
315 ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
316 qp->stats.dequeue_err_count++;
317 break;
318 }
319
320 retval = chacha20_poly1305_crypto_op(qp, ops[i], sess);
321 if (retval < 0) {
322 ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
323 qp->stats.dequeue_err_count++;
324 break;
325 }
326
327 handle_completed_chacha20_poly1305_crypto_op(qp, ops[i], sess);
328 }
329
330 qp->stats.dequeued_count += i;
331
332 return i;
333}
334
335struct rte_cryptodev_ops chacha20_poly1305_pmd_ops = {
336 .dev_configure = ipsec_mb_config,
337 .dev_start = ipsec_mb_start,
338 .dev_stop = ipsec_mb_stop,
339 .dev_close = ipsec_mb_close,
340
341 .stats_get = ipsec_mb_stats_get,
342 .stats_reset = ipsec_mb_stats_reset,
343
344 .dev_infos_get = ipsec_mb_info_get,
345
346 .queue_pair_setup = ipsec_mb_qp_setup,
347 .queue_pair_release = ipsec_mb_qp_release,
348
349 .sym_session_get_size = ipsec_mb_sym_session_get_size,
350 .sym_session_configure = ipsec_mb_sym_session_configure,
351 .sym_session_clear = ipsec_mb_sym_session_clear
352};
353
354struct rte_cryptodev_ops *rte_chacha20_poly1305_pmd_ops =
355 &chacha20_poly1305_pmd_ops;
356
357static int
358chacha20_poly1305_probe(struct rte_vdev_device *vdev)
359{
360 return ipsec_mb_create(vdev, IPSEC_MB_PMD_TYPE_CHACHA20_POLY1305);
361}
362
363static struct rte_vdev_driver cryptodev_chacha20_poly1305_pmd_drv = {
364 .probe = chacha20_poly1305_probe,
365 .remove = ipsec_mb_remove
366};
367
368static struct cryptodev_driver chacha20_poly1305_crypto_drv;
369
370RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_CHACHA20_POLY1305_PMD,
371 cryptodev_chacha20_poly1305_pmd_drv);
372RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_CHACHA20_POLY1305_PMD,
373 cryptodev_chacha20_poly1305_pmd);
374RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_CHACHA20_POLY1305_PMD,
375 "max_nb_queue_pairs=<int> socket_id=<int>");
376RTE_PMD_REGISTER_CRYPTO_DRIVER(chacha20_poly1305_crypto_drv,
377 cryptodev_chacha20_poly1305_pmd_drv.driver,
378 pmd_driver_id_chacha20_poly1305);
379
380
381RTE_INIT(ipsec_mb_register_chacha20_poly1305)
382{
383 struct ipsec_mb_internals *chacha_poly_data
384 = &ipsec_mb_pmds[IPSEC_MB_PMD_TYPE_CHACHA20_POLY1305];
385
386 chacha_poly_data->caps = chacha20_poly1305_capabilities;
387 chacha_poly_data->dequeue_burst = chacha20_poly1305_pmd_dequeue_burst;
388 chacha_poly_data->feature_flags =
389 RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
390 RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
391 RTE_CRYPTODEV_FF_IN_PLACE_SGL |
392 RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
393 RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
394 RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO |
395 RTE_CRYPTODEV_FF_SYM_SESSIONLESS;
396 chacha_poly_data->internals_priv_size = 0;
397 chacha_poly_data->ops = &chacha20_poly1305_pmd_ops;
398 chacha_poly_data->qp_priv_size =
399 sizeof(struct chacha20_poly1305_qp_data);
400 chacha_poly_data->session_configure =
401 chacha20_poly1305_session_configure;
402 chacha_poly_data->session_priv_size =
403 sizeof(struct chacha20_poly1305_session);
404}
405