Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2017-2018 Intel Corporation
3 : : */
4 : : #include <eal_export.h>
5 : : #include <rte_malloc.h>
6 : : #include <rte_hash.h>
7 : : #include <rte_jhash.h>
8 : : #include <rte_log.h>
9 : : #include <rte_mbuf.h>
10 : : #include <rte_cryptodev.h>
11 : :
12 : : #include "iotlb.h"
13 : : #include "rte_vhost_crypto.h"
14 : : #include "vhost.h"
15 : : #include "vhost_user.h"
16 : : #include "virtio_crypto.h"
17 : :
18 : : #define INHDR_LEN (sizeof(struct virtio_crypto_inhdr))
19 : : #define IV_OFFSET (sizeof(struct rte_crypto_op) + \
20 : : sizeof(struct rte_crypto_sym_op))
21 : :
22 [ - + ]: 252 : RTE_LOG_REGISTER_SUFFIX(vhost_crypto_logtype, crypto, INFO);
23 : : #define RTE_LOGTYPE_VHOST_CRYPTO vhost_crypto_logtype
24 : :
25 : : #define VC_LOG_ERR(...) \
26 : : RTE_LOG_LINE_PREFIX(ERR, VHOST_CRYPTO, "%s() line %u: ", \
27 : : __func__ RTE_LOG_COMMA __LINE__, __VA_ARGS__)
28 : :
29 : : #define VC_LOG_INFO(...) \
30 : : RTE_LOG_LINE_PREFIX(INFO, VHOST_CRYPTO, "%s() line %u: ", \
31 : : __func__ RTE_LOG_COMMA __LINE__, __VA_ARGS__)
32 : :
33 : : #ifdef RTE_LIBRTE_VHOST_DEBUG
34 : : #define VC_LOG_DBG(...) \
35 : : RTE_LOG_LINE_PREFIX(DEBUG, VHOST_CRYPTO, "%s() line %u: ", \
36 : : __func__ RTE_LOG_COMMA __LINE__, __VA_ARGS__)
37 : : #else
38 : : #define VC_LOG_DBG(...)
39 : : #endif
40 : :
41 : : #define VIRTIO_CRYPTO_FEATURES ((1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \
42 : : (1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
43 : : (1ULL << VIRTIO_RING_F_EVENT_IDX) | \
44 : : (1ULL << VIRTIO_NET_F_CTRL_VQ) | \
45 : : (1ULL << VIRTIO_F_VERSION_1) | \
46 : : (1ULL << VHOST_USER_F_PROTOCOL_FEATURES))
47 : :
48 : : #define IOVA_TO_VVA(t, dev, vq, a, l, p) \
49 : : ((t)(uintptr_t)vhost_iova_to_vva(dev, vq, a, l, p))
50 : :
51 : : /*
52 : : * vhost_crypto_desc is used to copy original vring_desc to the local buffer
53 : : * before processing (except the next index). The copy result will be an
54 : : * array of vhost_crypto_desc elements that follows the sequence of original
55 : : * vring_desc.next is arranged.
56 : : */
57 : : #define vhost_crypto_desc vring_desc
58 : :
59 : : struct vhost_crypto_session {
60 : : union {
61 : : struct rte_cryptodev_asym_session *asym;
62 : : struct rte_cryptodev_sym_session *sym;
63 : : };
64 : : enum rte_crypto_op_type type;
65 : : };
66 : :
67 : : static int
68 : 0 : cipher_algo_transform(uint32_t virtio_cipher_algo,
69 : : enum rte_crypto_cipher_algorithm *algo)
70 : : {
71 [ # # # # : 0 : switch (virtio_cipher_algo) {
# # # # #
# # # # ]
72 : 0 : case VIRTIO_CRYPTO_CIPHER_AES_CBC:
73 : 0 : *algo = RTE_CRYPTO_CIPHER_AES_CBC;
74 : 0 : break;
75 : 0 : case VIRTIO_CRYPTO_CIPHER_AES_CTR:
76 : 0 : *algo = RTE_CRYPTO_CIPHER_AES_CTR;
77 : 0 : break;
78 : 0 : case VIRTIO_CRYPTO_CIPHER_DES_ECB:
79 : 0 : *algo = -VIRTIO_CRYPTO_NOTSUPP;
80 : 0 : break;
81 : 0 : case VIRTIO_CRYPTO_CIPHER_DES_CBC:
82 : 0 : *algo = RTE_CRYPTO_CIPHER_DES_CBC;
83 : 0 : break;
84 : 0 : case VIRTIO_CRYPTO_CIPHER_3DES_ECB:
85 : 0 : *algo = RTE_CRYPTO_CIPHER_3DES_ECB;
86 : 0 : break;
87 : 0 : case VIRTIO_CRYPTO_CIPHER_3DES_CBC:
88 : 0 : *algo = RTE_CRYPTO_CIPHER_3DES_CBC;
89 : 0 : break;
90 : 0 : case VIRTIO_CRYPTO_CIPHER_3DES_CTR:
91 : 0 : *algo = RTE_CRYPTO_CIPHER_3DES_CTR;
92 : 0 : break;
93 : 0 : case VIRTIO_CRYPTO_CIPHER_KASUMI_F8:
94 : 0 : *algo = RTE_CRYPTO_CIPHER_KASUMI_F8;
95 : 0 : break;
96 : 0 : case VIRTIO_CRYPTO_CIPHER_SNOW3G_UEA2:
97 : 0 : *algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
98 : 0 : break;
99 : 0 : case VIRTIO_CRYPTO_CIPHER_AES_F8:
100 : 0 : *algo = RTE_CRYPTO_CIPHER_AES_F8;
101 : 0 : break;
102 : 0 : case VIRTIO_CRYPTO_CIPHER_AES_XTS:
103 : 0 : *algo = RTE_CRYPTO_CIPHER_AES_XTS;
104 : 0 : break;
105 : 0 : case VIRTIO_CRYPTO_CIPHER_ZUC_EEA3:
106 : 0 : *algo = RTE_CRYPTO_CIPHER_ZUC_EEA3;
107 : 0 : break;
108 : : default:
109 : : return -VIRTIO_CRYPTO_BADMSG;
110 : : break;
111 : : }
112 : :
113 : : return 0;
114 : : }
115 : :
116 : : static int
117 : 0 : auth_algo_transform(uint32_t virtio_auth_algo,
118 : : enum rte_crypto_auth_algorithm *algo)
119 : : {
120 [ # # # # : 0 : switch (virtio_auth_algo) {
# # # # #
# # # # #
# ]
121 : 0 : case VIRTIO_CRYPTO_NO_MAC:
122 : 0 : *algo = RTE_CRYPTO_AUTH_NULL;
123 : 0 : break;
124 : 0 : case VIRTIO_CRYPTO_MAC_HMAC_MD5:
125 : 0 : *algo = RTE_CRYPTO_AUTH_MD5_HMAC;
126 : 0 : break;
127 : 0 : case VIRTIO_CRYPTO_MAC_HMAC_SHA1:
128 : 0 : *algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
129 : 0 : break;
130 : 0 : case VIRTIO_CRYPTO_MAC_HMAC_SHA_224:
131 : 0 : *algo = RTE_CRYPTO_AUTH_SHA224_HMAC;
132 : 0 : break;
133 : 0 : case VIRTIO_CRYPTO_MAC_HMAC_SHA_256:
134 : 0 : *algo = RTE_CRYPTO_AUTH_SHA256_HMAC;
135 : 0 : break;
136 : 0 : case VIRTIO_CRYPTO_MAC_HMAC_SHA_384:
137 : 0 : *algo = RTE_CRYPTO_AUTH_SHA384_HMAC;
138 : 0 : break;
139 : 0 : case VIRTIO_CRYPTO_MAC_HMAC_SHA_512:
140 : 0 : *algo = RTE_CRYPTO_AUTH_SHA512_HMAC;
141 : 0 : break;
142 : 0 : case VIRTIO_CRYPTO_MAC_CMAC_AES:
143 : 0 : *algo = RTE_CRYPTO_AUTH_AES_CMAC;
144 : 0 : break;
145 : 0 : case VIRTIO_CRYPTO_MAC_KASUMI_F9:
146 : 0 : *algo = RTE_CRYPTO_AUTH_KASUMI_F9;
147 : 0 : break;
148 : 0 : case VIRTIO_CRYPTO_MAC_SNOW3G_UIA2:
149 : 0 : *algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2;
150 : 0 : break;
151 : 0 : case VIRTIO_CRYPTO_MAC_GMAC_AES:
152 : 0 : *algo = RTE_CRYPTO_AUTH_AES_GMAC;
153 : 0 : break;
154 : 0 : case VIRTIO_CRYPTO_MAC_CBCMAC_AES:
155 : 0 : *algo = RTE_CRYPTO_AUTH_AES_CBC_MAC;
156 : 0 : break;
157 : 0 : case VIRTIO_CRYPTO_MAC_XCBC_AES:
158 : 0 : *algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC;
159 : 0 : break;
160 : : case VIRTIO_CRYPTO_MAC_CMAC_3DES:
161 : : case VIRTIO_CRYPTO_MAC_GMAC_TWOFISH:
162 : : case VIRTIO_CRYPTO_MAC_CBCMAC_KASUMI_F9:
163 : : return -VIRTIO_CRYPTO_NOTSUPP;
164 : 0 : default:
165 : 0 : return -VIRTIO_CRYPTO_BADMSG;
166 : : }
167 : :
168 : : return 0;
169 : : }
170 : :
171 : : static int get_iv_len(enum rte_crypto_cipher_algorithm algo)
172 : : {
173 : : int len;
174 : :
175 : 0 : switch (algo) {
176 : : case RTE_CRYPTO_CIPHER_3DES_CBC:
177 : : len = 8;
178 : : break;
179 : : case RTE_CRYPTO_CIPHER_3DES_CTR:
180 : : len = 8;
181 : : break;
182 : : case RTE_CRYPTO_CIPHER_3DES_ECB:
183 : : len = 8;
184 : : break;
185 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
186 : : len = 16;
187 : 0 : break;
188 : :
189 : : /* TODO: add common algos */
190 : :
191 : 0 : default:
192 : : len = -1;
193 : 0 : break;
194 : : }
195 : :
196 : : return len;
197 : : }
198 : :
199 : : /**
200 : : * vhost_crypto struct is used to maintain a number of virtio_cryptos and
201 : : * one DPDK crypto device that deals with all crypto workloads. It is declared
202 : : * here and defined in vhost_crypto.c
203 : : */
204 : : struct __rte_cache_aligned vhost_crypto {
205 : : /** Used to lookup DPDK Cryptodev Session based on VIRTIO crypto
206 : : * session ID.
207 : : */
208 : : struct rte_hash *session_map;
209 : : struct rte_mempool *mbuf_pool;
210 : : struct rte_mempool *sess_pool;
211 : : struct rte_mempool *wb_pool;
212 : :
213 : : /** DPDK cryptodev ID */
214 : : uint8_t cid;
215 : : uint16_t nb_qps;
216 : :
217 : : uint64_t last_session_id;
218 : :
219 : : uint64_t cache_sym_session_id;
220 : : struct rte_cryptodev_sym_session *cache_sym_session;
221 : : uint64_t cache_asym_session_id;
222 : : struct rte_cryptodev_asym_session *cache_asym_session;
223 : : /** socket id for the device */
224 : : int socket_id;
225 : :
226 : : struct virtio_net *dev;
227 : :
228 : : uint8_t option;
229 : : };
230 : :
231 : : struct vhost_crypto_writeback_data {
232 : : uint8_t *src;
233 : : uint8_t *dst;
234 : : uint64_t len;
235 : : struct vhost_crypto_writeback_data *next;
236 : : };
237 : :
238 : : struct vhost_crypto_data_req {
239 : : struct vring_desc *head;
240 : : struct virtio_net *dev;
241 : : struct virtio_crypto_inhdr *inhdr;
242 : : struct vhost_virtqueue *vq;
243 : : struct vhost_crypto_writeback_data *wb;
244 : : struct rte_mempool *wb_pool;
245 : : uint16_t desc_idx;
246 : : uint16_t len;
247 : : uint16_t zero_copy;
248 : : };
249 : :
250 : : static int
251 : 0 : transform_cipher_param(struct rte_crypto_sym_xform *xform,
252 : : VhostUserCryptoSymSessionParam *param)
253 : : {
254 : : int ret;
255 : :
256 : 0 : ret = cipher_algo_transform(param->cipher_algo, &xform->cipher.algo);
257 [ # # ]: 0 : if (unlikely(ret < 0))
258 : : return ret;
259 : :
260 [ # # ]: 0 : if (param->cipher_key_len > VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH) {
261 : : VC_LOG_DBG("Invalid cipher key length");
262 : : return -VIRTIO_CRYPTO_BADMSG;
263 : : }
264 : :
265 : 0 : xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
266 : 0 : xform->cipher.key.length = param->cipher_key_len;
267 [ # # ]: 0 : if (xform->cipher.key.length > 0)
268 : 0 : xform->cipher.key.data = param->cipher_key_buf;
269 [ # # ]: 0 : if (param->dir == VIRTIO_CRYPTO_OP_ENCRYPT)
270 : 0 : xform->cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
271 [ # # ]: 0 : else if (param->dir == VIRTIO_CRYPTO_OP_DECRYPT)
272 : 0 : xform->cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
273 : : else {
274 : : VC_LOG_DBG("Bad operation type");
275 : : return -VIRTIO_CRYPTO_BADMSG;
276 : : }
277 : :
278 [ # # # ]: 0 : ret = get_iv_len(xform->cipher.algo);
279 [ # # ]: 0 : if (unlikely(ret < 0))
280 : : return ret;
281 : 0 : xform->cipher.iv.length = (uint16_t)ret;
282 : 0 : xform->cipher.iv.offset = IV_OFFSET;
283 : 0 : return 0;
284 : : }
285 : :
286 : : static int
287 : 0 : transform_chain_param(struct rte_crypto_sym_xform *xforms,
288 : : VhostUserCryptoSymSessionParam *param)
289 : : {
290 : : struct rte_crypto_sym_xform *xform_cipher, *xform_auth;
291 : : int ret;
292 : :
293 [ # # # ]: 0 : switch (param->chaining_dir) {
294 : 0 : case VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER:
295 : : xform_auth = xforms;
296 : 0 : xform_cipher = xforms->next;
297 : 0 : xform_cipher->cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
298 : 0 : xform_auth->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
299 : 0 : break;
300 : 0 : case VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH:
301 : : xform_cipher = xforms;
302 : 0 : xform_auth = xforms->next;
303 : 0 : xform_cipher->cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
304 : 0 : xform_auth->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
305 : 0 : break;
306 : : default:
307 : : return -VIRTIO_CRYPTO_BADMSG;
308 : : }
309 : :
310 : : /* cipher */
311 : 0 : ret = cipher_algo_transform(param->cipher_algo,
312 : : &xform_cipher->cipher.algo);
313 [ # # ]: 0 : if (unlikely(ret < 0))
314 : : return ret;
315 : :
316 [ # # ]: 0 : if (param->cipher_key_len > VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH) {
317 : : VC_LOG_DBG("Invalid cipher key length");
318 : : return -VIRTIO_CRYPTO_BADMSG;
319 : : }
320 : :
321 : 0 : xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
322 : 0 : xform_cipher->cipher.key.length = param->cipher_key_len;
323 : 0 : xform_cipher->cipher.key.data = param->cipher_key_buf;
324 [ # # # ]: 0 : ret = get_iv_len(xform_cipher->cipher.algo);
325 [ # # ]: 0 : if (unlikely(ret < 0))
326 : : return ret;
327 : 0 : xform_cipher->cipher.iv.length = (uint16_t)ret;
328 : 0 : xform_cipher->cipher.iv.offset = IV_OFFSET;
329 : :
330 : : /* auth */
331 : 0 : xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH;
332 : 0 : ret = auth_algo_transform(param->hash_algo, &xform_auth->auth.algo);
333 [ # # ]: 0 : if (unlikely(ret < 0))
334 : : return ret;
335 : :
336 [ # # ]: 0 : if (param->auth_key_len > VHOST_USER_CRYPTO_MAX_HMAC_KEY_LENGTH) {
337 : : VC_LOG_DBG("Invalid auth key length");
338 : : return -VIRTIO_CRYPTO_BADMSG;
339 : : }
340 : :
341 : 0 : xform_auth->auth.digest_length = param->digest_len;
342 : 0 : xform_auth->auth.key.length = param->auth_key_len;
343 : 0 : xform_auth->auth.key.data = param->auth_key_buf;
344 : :
345 : 0 : return 0;
346 : : }
347 : :
348 : : static void
349 : 0 : vhost_crypto_create_sym_sess(struct vhost_crypto *vcrypto,
350 : : VhostUserCryptoSessionParam *sess_param)
351 : : {
352 : 0 : struct rte_crypto_sym_xform xform1 = {0}, xform2 = {0};
353 : : struct vhost_crypto_session *vhost_session;
354 : : struct rte_cryptodev_sym_session *session;
355 : : int ret;
356 : :
357 [ # # # ]: 0 : switch (sess_param->u.sym_sess.op_type) {
358 : 0 : case VIRTIO_CRYPTO_SYM_OP_NONE:
359 : : case VIRTIO_CRYPTO_SYM_OP_CIPHER:
360 : 0 : ret = transform_cipher_param(&xform1, &sess_param->u.sym_sess);
361 [ # # ]: 0 : if (unlikely(ret)) {
362 : 0 : VC_LOG_ERR("Error transform session msg (%i)", ret);
363 : 0 : sess_param->session_id = ret;
364 : 0 : return;
365 : : }
366 : : break;
367 : 0 : case VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:
368 [ # # ]: 0 : if (unlikely(sess_param->u.sym_sess.hash_mode !=
369 : : VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH)) {
370 : 0 : sess_param->session_id = -VIRTIO_CRYPTO_NOTSUPP;
371 : 0 : VC_LOG_ERR("Error transform session message (%i)",
372 : : -VIRTIO_CRYPTO_NOTSUPP);
373 : 0 : return;
374 : : }
375 : :
376 : 0 : xform1.next = &xform2;
377 : :
378 : 0 : ret = transform_chain_param(&xform1, &sess_param->u.sym_sess);
379 [ # # ]: 0 : if (unlikely(ret)) {
380 : 0 : VC_LOG_ERR("Error transform session message (%i)", ret);
381 : 0 : sess_param->session_id = ret;
382 : 0 : return;
383 : : }
384 : :
385 : : break;
386 : 0 : default:
387 : 0 : VC_LOG_ERR("Algorithm not yet supported");
388 : 0 : sess_param->session_id = -VIRTIO_CRYPTO_NOTSUPP;
389 : 0 : return;
390 : : }
391 : :
392 : 0 : session = rte_cryptodev_sym_session_create(vcrypto->cid, &xform1,
393 : : vcrypto->sess_pool);
394 [ # # ]: 0 : if (!session) {
395 : 0 : VC_LOG_ERR("Failed to create session");
396 : 0 : sess_param->session_id = -VIRTIO_CRYPTO_ERR;
397 : 0 : return;
398 : : }
399 : :
400 : 0 : vhost_session = rte_zmalloc(NULL, sizeof(*vhost_session), 0);
401 [ # # ]: 0 : if (vhost_session == NULL) {
402 : 0 : VC_LOG_ERR("Failed to alloc session memory");
403 : 0 : goto error_exit;
404 : : }
405 : :
406 : 0 : vhost_session->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
407 : 0 : vhost_session->sym = session;
408 : :
409 : : /* insert session to map */
410 [ # # ]: 0 : if ((rte_hash_add_key_data(vcrypto->session_map,
411 : 0 : &vcrypto->last_session_id, vhost_session) < 0)) {
412 : 0 : VC_LOG_ERR("Failed to insert session to hash table");
413 : 0 : goto error_exit;
414 : : }
415 : :
416 : 0 : VC_LOG_INFO("Session %"PRIu64" created for vdev %i.",
417 : : vcrypto->last_session_id, vcrypto->dev->vid);
418 : :
419 : 0 : sess_param->session_id = vcrypto->last_session_id;
420 : 0 : vcrypto->last_session_id++;
421 : 0 : return;
422 : :
423 : 0 : error_exit:
424 [ # # ]: 0 : if (rte_cryptodev_sym_session_free(vcrypto->cid, session) < 0)
425 : 0 : VC_LOG_ERR("Failed to free session");
426 : :
427 : 0 : sess_param->session_id = -VIRTIO_CRYPTO_ERR;
428 : 0 : rte_free(vhost_session);
429 : : }
430 : :
431 : : static int
432 : : tlv_decode(uint8_t *tlv, uint8_t type, uint8_t **data, size_t *data_len)
433 : : {
434 : : size_t tlen = -EINVAL, len;
435 : :
436 [ # # ]: 0 : if (tlv[0] != type)
437 : : return -EINVAL;
438 : :
439 [ # # # # : 0 : if (tlv[1] == 0x82) {
# # # # #
# # # # #
# # # # ]
440 : 0 : len = (tlv[2] << 8) | tlv[3];
441 : 0 : *data = &tlv[4];
442 : 0 : tlen = len + 4;
443 [ # # # # : 0 : } else if (tlv[1] == 0x81) {
# # # # #
# # # # #
# # # # ]
444 : 0 : len = tlv[2];
445 : 0 : *data = &tlv[3];
446 : 0 : tlen = len + 3;
447 : : } else {
448 : 0 : len = tlv[1];
449 : 0 : *data = &tlv[2];
450 : 0 : tlen = len + 2;
451 : : }
452 : :
453 : : *data_len = len;
454 : 0 : return tlen;
455 : : }
456 : :
457 : : static int
458 : 0 : virtio_crypto_asym_rsa_der_to_xform(uint8_t *der, size_t der_len,
459 : : struct rte_crypto_asym_xform *xform)
460 : : {
461 : : uint8_t *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, *dp = NULL,
462 : : *dq = NULL, *qinv = NULL, *v = NULL, *tlv;
463 : : size_t nlen, elen, dlen, plen, qlen, dplen, dqlen, qinvlen, vlen;
464 : : int len;
465 : :
466 : : RTE_SET_USED(der_len);
467 : :
468 [ # # ]: 0 : if (der[0] != 0x30)
469 : : return -EINVAL;
470 : :
471 [ # # ]: 0 : if (der[1] == 0x82)
472 : 0 : tlv = &der[4];
473 [ # # ]: 0 : else if (der[1] == 0x81)
474 : 0 : tlv = &der[3];
475 : : else
476 : : return -EINVAL;
477 : :
478 : : len = tlv_decode(tlv, 0x02, &v, &vlen);
479 [ # # # # : 0 : if (len < 0 || v[0] != 0x0 || vlen != 1)
# # ]
480 : : return -EINVAL;
481 : :
482 [ # # ]: 0 : tlv = tlv + len;
483 : : len = tlv_decode(tlv, 0x02, &n, &nlen);
484 [ # # ]: 0 : if (len < 0)
485 : : return len;
486 : :
487 [ # # ]: 0 : tlv = tlv + len;
488 : : len = tlv_decode(tlv, 0x02, &e, &elen);
489 [ # # ]: 0 : if (len < 0)
490 : : return len;
491 : :
492 [ # # ]: 0 : tlv = tlv + len;
493 : : len = tlv_decode(tlv, 0x02, &d, &dlen);
494 [ # # ]: 0 : if (len < 0)
495 : : return len;
496 : :
497 [ # # ]: 0 : tlv = tlv + len;
498 : : len = tlv_decode(tlv, 0x02, &p, &plen);
499 [ # # ]: 0 : if (len < 0)
500 : : return len;
501 : :
502 [ # # ]: 0 : tlv = tlv + len;
503 : : len = tlv_decode(tlv, 0x02, &q, &qlen);
504 [ # # ]: 0 : if (len < 0)
505 : : return len;
506 : :
507 [ # # ]: 0 : tlv = tlv + len;
508 : : len = tlv_decode(tlv, 0x02, &dp, &dplen);
509 [ # # ]: 0 : if (len < 0)
510 : : return len;
511 : :
512 [ # # ]: 0 : tlv = tlv + len;
513 : : len = tlv_decode(tlv, 0x02, &dq, &dqlen);
514 [ # # ]: 0 : if (len < 0)
515 : : return len;
516 : :
517 [ # # ]: 0 : tlv = tlv + len;
518 : : len = tlv_decode(tlv, 0x02, &qinv, &qinvlen);
519 [ # # ]: 0 : if (len < 0)
520 : : return len;
521 : :
522 : 0 : xform->rsa.n.data = n;
523 : 0 : xform->rsa.n.length = nlen;
524 : 0 : xform->rsa.e.data = e;
525 : 0 : xform->rsa.e.length = elen;
526 : 0 : xform->rsa.d.data = d;
527 : 0 : xform->rsa.d.length = dlen;
528 : 0 : xform->rsa.qt.p.data = p;
529 : 0 : xform->rsa.qt.p.length = plen;
530 : 0 : xform->rsa.qt.q.data = q;
531 : 0 : xform->rsa.qt.q.length = qlen;
532 : 0 : xform->rsa.qt.dP.data = dp;
533 : 0 : xform->rsa.qt.dP.length = dplen;
534 : 0 : xform->rsa.qt.dQ.data = dq;
535 : 0 : xform->rsa.qt.dQ.length = dqlen;
536 : 0 : xform->rsa.qt.qInv.data = qinv;
537 : 0 : xform->rsa.qt.qInv.length = qinvlen;
538 : :
539 : : RTE_ASSERT(tlv + len == der + der_len);
540 : 0 : return 0;
541 : : }
542 : :
543 : : static int
544 : 0 : rsa_param_transform(struct rte_crypto_asym_xform *xform,
545 : : VhostUserCryptoAsymSessionParam *param)
546 : : {
547 : : int ret;
548 : :
549 : 0 : ret = virtio_crypto_asym_rsa_der_to_xform(param->key_buf, param->key_len, xform);
550 [ # # ]: 0 : if (ret < 0)
551 : : return ret;
552 : :
553 [ # # # ]: 0 : switch (param->u.rsa.padding_algo) {
554 : 0 : case VIRTIO_CRYPTO_RSA_RAW_PADDING:
555 : 0 : xform->rsa.padding.type = RTE_CRYPTO_RSA_PADDING_NONE;
556 : 0 : break;
557 : 0 : case VIRTIO_CRYPTO_RSA_PKCS1_PADDING:
558 : 0 : xform->rsa.padding.type = RTE_CRYPTO_RSA_PADDING_PKCS1_5;
559 : 0 : break;
560 : 0 : default:
561 : 0 : VC_LOG_ERR("Unknown padding type");
562 : 0 : return -EINVAL;
563 : : }
564 : :
565 : 0 : xform->rsa.key_type = RTE_RSA_KEY_TYPE_QT;
566 : 0 : xform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;
567 : 0 : return 0;
568 : : }
569 : :
570 : : static void
571 : 0 : vhost_crypto_create_asym_sess(struct vhost_crypto *vcrypto,
572 : : VhostUserCryptoSessionParam *sess_param)
573 : : {
574 : 0 : struct rte_cryptodev_asym_session *session = NULL;
575 : : struct vhost_crypto_session *vhost_session;
576 : 0 : struct rte_crypto_asym_xform xform = {0};
577 : : int ret;
578 : :
579 [ # # ]: 0 : switch (sess_param->u.asym_sess.algo) {
580 : 0 : case VIRTIO_CRYPTO_AKCIPHER_RSA:
581 : 0 : ret = rsa_param_transform(&xform, &sess_param->u.asym_sess);
582 [ # # ]: 0 : if (unlikely(ret < 0)) {
583 : 0 : VC_LOG_ERR("Error transform session msg (%i)", ret);
584 : 0 : sess_param->session_id = ret;
585 : 0 : return;
586 : : }
587 : : break;
588 : 0 : default:
589 : 0 : VC_LOG_ERR("Invalid op algo");
590 : 0 : sess_param->session_id = -VIRTIO_CRYPTO_ERR;
591 : 0 : return;
592 : : }
593 : :
594 : 0 : ret = rte_cryptodev_asym_session_create(vcrypto->cid, &xform,
595 : : vcrypto->sess_pool, (void *)&session);
596 [ # # ]: 0 : if (session == NULL) {
597 : 0 : VC_LOG_ERR("Failed to create session");
598 : 0 : sess_param->session_id = -VIRTIO_CRYPTO_ERR;
599 : 0 : return;
600 : : }
601 : :
602 : 0 : vhost_session = rte_zmalloc(NULL, sizeof(*vhost_session), 0);
603 [ # # ]: 0 : if (vhost_session == NULL) {
604 : 0 : VC_LOG_ERR("Failed to alloc session memory");
605 : 0 : goto error_exit;
606 : : }
607 : :
608 : 0 : vhost_session->type = RTE_CRYPTO_OP_TYPE_ASYMMETRIC;
609 : 0 : vhost_session->asym = session;
610 : :
611 : : /* insert session to map */
612 [ # # ]: 0 : if ((rte_hash_add_key_data(vcrypto->session_map,
613 : 0 : &vcrypto->last_session_id, vhost_session) < 0)) {
614 : 0 : VC_LOG_ERR("Failed to insert session to hash table");
615 : 0 : goto error_exit;
616 : : }
617 : :
618 : 0 : VC_LOG_INFO("Session %"PRIu64" created for vdev %i.",
619 : : vcrypto->last_session_id, vcrypto->dev->vid);
620 : :
621 : 0 : sess_param->session_id = vcrypto->last_session_id;
622 : 0 : vcrypto->last_session_id++;
623 : 0 : return;
624 : :
625 : 0 : error_exit:
626 [ # # ]: 0 : if (rte_cryptodev_asym_session_free(vcrypto->cid, session) < 0)
627 : 0 : VC_LOG_ERR("Failed to free session");
628 : 0 : sess_param->session_id = -VIRTIO_CRYPTO_ERR;
629 : 0 : rte_free(vhost_session);
630 : : }
631 : :
632 : : static void
633 : 0 : vhost_crypto_create_sess(struct vhost_crypto *vcrypto,
634 : : VhostUserCryptoSessionParam *sess_param)
635 : : {
636 [ # # ]: 0 : if (sess_param->op_code == VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION)
637 : 0 : vhost_crypto_create_asym_sess(vcrypto, sess_param);
638 : : else
639 : 0 : vhost_crypto_create_sym_sess(vcrypto, sess_param);
640 : 0 : }
641 : :
642 : : static int
643 : 0 : vhost_crypto_close_sess(struct vhost_crypto *vcrypto, uint64_t session_id)
644 : : {
645 : 0 : struct vhost_crypto_session *vhost_session = NULL;
646 : 0 : uint64_t sess_id = session_id;
647 : : int ret;
648 : :
649 : 0 : ret = rte_hash_lookup_data(vcrypto->session_map, &sess_id,
650 : : (void **)&vhost_session);
651 [ # # ]: 0 : if (unlikely(ret < 0)) {
652 : 0 : VC_LOG_ERR("Failed to find session for id %"PRIu64".", session_id);
653 : 0 : return -VIRTIO_CRYPTO_INVSESS;
654 : : }
655 : :
656 [ # # ]: 0 : if (vhost_session->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
657 [ # # ]: 0 : if (rte_cryptodev_sym_session_free(vcrypto->cid,
658 : 0 : vhost_session->sym) < 0) {
659 : : VC_LOG_DBG("Failed to free session");
660 : : return -VIRTIO_CRYPTO_ERR;
661 : : }
662 [ # # ]: 0 : } else if (vhost_session->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
663 [ # # ]: 0 : if (rte_cryptodev_asym_session_free(vcrypto->cid,
664 : 0 : vhost_session->asym) < 0) {
665 : : VC_LOG_DBG("Failed to free session");
666 : : return -VIRTIO_CRYPTO_ERR;
667 : : }
668 : : } else {
669 : 0 : VC_LOG_ERR("Invalid session for id %"PRIu64".", session_id);
670 : 0 : return -VIRTIO_CRYPTO_INVSESS;
671 : : }
672 : :
673 [ # # ]: 0 : if (rte_hash_del_key(vcrypto->session_map, &sess_id) < 0) {
674 : : VC_LOG_DBG("Failed to delete session from hash table.");
675 : : return -VIRTIO_CRYPTO_ERR;
676 : : }
677 : :
678 : 0 : VC_LOG_INFO("Session %"PRIu64" deleted for vdev %i.", sess_id,
679 : : vcrypto->dev->vid);
680 : :
681 : 0 : rte_free(vhost_session);
682 : 0 : return 0;
683 : : }
684 : :
685 : : static enum rte_vhost_msg_result
686 [ # # ]: 0 : vhost_crypto_msg_post_handler(int vid, void *msg)
687 : : {
688 : : struct virtio_net *dev = get_device(vid);
689 : : struct vhost_crypto *vcrypto;
690 : : struct vhu_msg_context *ctx = msg;
691 : : enum rte_vhost_msg_result ret = RTE_VHOST_MSG_RESULT_OK;
692 : :
693 [ # # ]: 0 : if (dev == NULL) {
694 : 0 : VC_LOG_ERR("Invalid vid %i", vid);
695 : 0 : return RTE_VHOST_MSG_RESULT_ERR;
696 : : }
697 : :
698 : 0 : vcrypto = dev->extern_data;
699 [ # # ]: 0 : if (vcrypto == NULL) {
700 : 0 : VC_LOG_ERR("Cannot find required data, is it initialized?");
701 : 0 : return RTE_VHOST_MSG_RESULT_ERR;
702 : : }
703 : :
704 [ # # # ]: 0 : switch (ctx->msg.request.frontend) {
705 : 0 : case VHOST_USER_CRYPTO_CREATE_SESS:
706 : 0 : vhost_crypto_create_sess(vcrypto,
707 : : &ctx->msg.payload.crypto_session);
708 : 0 : ctx->fd_num = 0;
709 : : ret = RTE_VHOST_MSG_RESULT_REPLY;
710 : 0 : break;
711 : 0 : case VHOST_USER_CRYPTO_CLOSE_SESS:
712 [ # # ]: 0 : if (vhost_crypto_close_sess(vcrypto, ctx->msg.payload.u64))
713 : : ret = RTE_VHOST_MSG_RESULT_ERR;
714 : : break;
715 : : default:
716 : : ret = RTE_VHOST_MSG_RESULT_NOT_HANDLED;
717 : : break;
718 : : }
719 : :
720 : : return ret;
721 : : }
722 : :
723 : : static __rte_always_inline struct vhost_crypto_desc *
724 : : find_write_desc(struct vhost_crypto_desc *head, struct vhost_crypto_desc *desc,
725 : : uint32_t max_n_descs)
726 : : {
727 [ # # # # : 0 : if (desc < head)
# # # # ]
728 : : return NULL;
729 : :
730 [ # # # # : 0 : while (desc - head < (int)max_n_descs) {
# # # # #
# # # # #
# # ]
731 [ # # # # : 0 : if (desc->flags & VRING_DESC_F_WRITE)
# # # # #
# # # # #
# # ]
732 : : return desc;
733 : 0 : desc++;
734 : : }
735 : :
736 : : return NULL;
737 : : }
738 : :
739 : : static __rte_always_inline struct virtio_crypto_inhdr *
740 : : reach_inhdr(struct virtio_net *dev, struct vhost_virtqueue *vq,
741 : : struct vhost_crypto_desc *head,
742 : : uint32_t max_n_descs)
743 : : __rte_requires_shared_capability(&vq->iotlb_lock)
744 : : {
745 : : struct virtio_crypto_inhdr *inhdr;
746 : 0 : struct vhost_crypto_desc *last = head + (max_n_descs - 1);
747 : 0 : uint64_t dlen = last->len;
748 : :
749 : 0 : if (unlikely(dlen != sizeof(*inhdr)))
750 : : return NULL;
751 : :
752 [ # # # # ]: 0 : inhdr = IOVA_TO_VVA(struct virtio_crypto_inhdr *, dev, vq,
753 : : last->addr, &dlen, VHOST_ACCESS_WO);
754 [ # # # # : 0 : if (unlikely(!inhdr || dlen != last->len))
# # # # ]
755 : 0 : return NULL;
756 : :
757 : : return inhdr;
758 : : }
759 : :
760 : : static __rte_always_inline int
761 : : move_desc(struct vhost_crypto_desc *head,
762 : : struct vhost_crypto_desc **cur_desc,
763 : : uint32_t size, uint32_t max_n_descs)
764 : : {
765 : : struct vhost_crypto_desc *desc = *cur_desc;
766 : 0 : int left = size - desc->len;
767 : :
768 : 0 : while (desc->flags & VRING_DESC_F_NEXT && left > 0 &&
769 [ # # # # : 0 : desc >= head &&
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
770 [ # # # # : 0 : desc - head < (int)max_n_descs) {
# # # # #
# # # # #
# # # # #
# ]
771 : 0 : desc++;
772 : 0 : left -= desc->len;
773 : : }
774 : :
775 [ # # # # : 0 : if (unlikely(left > 0))
# # # # #
# # # # #
# # # # #
# ]
776 : : return -1;
777 : :
778 [ # # # # : 0 : if (unlikely(head - desc == (int)max_n_descs))
# # # # #
# # # # #
# # # # #
# ]
779 : : *cur_desc = NULL;
780 : : else
781 : 0 : *cur_desc = desc + 1;
782 : :
783 : : return 0;
784 : : }
785 : :
786 : : static __rte_always_inline void *
787 : : get_data_ptr(struct vhost_virtqueue *vq, struct vhost_crypto_data_req *vc_req,
788 : : struct vhost_crypto_desc *cur_desc,
789 : : uint8_t perm)
790 : : __rte_requires_shared_capability(&vq->iotlb_lock)
791 : : {
792 : : void *data;
793 : 0 : uint64_t dlen = cur_desc->len;
794 : :
795 [ # # # # : 0 : data = IOVA_TO_VVA(void *, vc_req->dev, vq,
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
796 : : cur_desc->addr, &dlen, perm);
797 [ # # # # : 0 : if (unlikely(!data || dlen != cur_desc->len)) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
798 : 0 : VC_LOG_ERR("Failed to map object");
799 : 0 : return NULL;
800 : : }
801 : :
802 : : return data;
803 : : }
804 : :
805 : : static __rte_always_inline uint32_t
806 : : copy_data_from_desc(void *dst, struct virtio_net *dev,
807 : : struct vhost_virtqueue *vq, struct vhost_crypto_desc *desc, uint32_t size)
808 : : __rte_requires_shared_capability(&vq->iotlb_lock)
809 : : {
810 : : uint64_t remain;
811 : : uint64_t addr;
812 : :
813 : 0 : remain = RTE_MIN(desc->len, size);
814 : 0 : addr = desc->addr;
815 : : do {
816 : : uint64_t len;
817 : : void *src;
818 : :
819 [ # # # # : 0 : len = remain;
# # # # #
# # # # #
# # # # #
# # # #
# ]
820 : 0 : src = IOVA_TO_VVA(void *, dev, vq,
821 : : addr, &len, VHOST_ACCESS_RO);
822 [ # # # # : 0 : if (unlikely(src == NULL || len == 0))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
823 : 0 : return 0;
824 : :
825 : : rte_memcpy(dst, src, len);
826 : 0 : remain -= len;
827 : : /* cast is needed for 32-bit architecture */
828 : 0 : dst = RTE_PTR_ADD(dst, (size_t)len);
829 : 0 : addr += len;
830 [ # # # # : 0 : } while (unlikely(remain != 0));
# # # # #
# # # # #
# # # # #
# # # #
# ]
831 : :
832 : : return RTE_MIN(desc->len, size);
833 : : }
834 : :
835 : :
836 : : static __rte_always_inline int
837 : : copy_data(void *data, struct virtio_net *dev, struct vhost_virtqueue *vq,
838 : : struct vhost_crypto_desc *head, struct vhost_crypto_desc **cur_desc,
839 : : uint32_t size, uint32_t max_n_descs)
840 : : __rte_requires_shared_capability(&vq->iotlb_lock)
841 : : {
842 : : struct vhost_crypto_desc *desc = *cur_desc;
843 : : uint32_t left = size;
844 : :
845 : : do {
846 : : uint32_t copied;
847 : :
848 : : copied = copy_data_from_desc(data, dev, vq, desc, left);
849 [ # # # # : 0 : if (copied == 0)
# # # # #
# # # # #
# # # # #
# # # #
# ]
850 : : return -1;
851 : 0 : left -= copied;
852 : 0 : data = RTE_PTR_ADD(data, copied);
853 [ # # # # : 0 : } while (left != 0 && ++desc < head + max_n_descs);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
854 : :
855 [ # # # # : 0 : if (unlikely(left != 0))
# # # # #
# # # # #
# # # # #
# # # #
# ]
856 : : return -1;
857 : :
858 [ # # # # : 0 : if (unlikely(desc == head + max_n_descs))
# # # # #
# # # # #
# # # # #
# ]
859 : : *cur_desc = NULL;
860 : : else
861 : 0 : *cur_desc = desc + 1;
862 : :
863 : : return 0;
864 : : }
865 : :
866 : : static void
867 : 0 : write_back_data(struct vhost_crypto_data_req *vc_req)
868 : : {
869 : 0 : struct vhost_crypto_writeback_data *wb_data = vc_req->wb, *wb_last;
870 : :
871 [ # # ]: 0 : while (wb_data) {
872 [ # # ]: 0 : rte_memcpy(wb_data->dst, wb_data->src, wb_data->len);
873 [ # # ]: 0 : memset(wb_data->src, 0, wb_data->len);
874 : : wb_last = wb_data;
875 : 0 : wb_data = wb_data->next;
876 [ # # ]: 0 : rte_mempool_put(vc_req->wb_pool, wb_last);
877 : : }
878 : 0 : }
879 : :
880 : : static void
881 : 0 : free_wb_data(struct vhost_crypto_writeback_data *wb_data,
882 : : struct rte_mempool *mp)
883 : : {
884 [ # # ]: 0 : while (wb_data->next != NULL)
885 : 0 : free_wb_data(wb_data->next, mp);
886 : :
887 : 0 : rte_mempool_put(mp, wb_data);
888 : 0 : }
889 : :
890 : : /**
891 : : * The function will allocate a vhost_crypto_writeback_data linked list
892 : : * containing the source and destination data pointers for the write back
893 : : * operation after dequeued from Cryptodev PMD queues.
894 : : *
895 : : * @param vc_req
896 : : * The vhost crypto data request pointer
897 : : * @param cur_desc
898 : : * The pointer of the current in use descriptor pointer. The content of
899 : : * cur_desc is expected to be updated after the function execution.
900 : : * @param end_wb_data
901 : : * The last write back data element to be returned. It is used only in cipher
902 : : * and hash chain operations.
903 : : * @param src
904 : : * The source data pointer
905 : : * @param offset
906 : : * The offset to both source and destination data. For source data the offset
907 : : * is the number of bytes between src and start point of cipher operation. For
908 : : * destination data the offset is the number of bytes from *cur_desc->addr
909 : : * to the point where the src will be written to.
910 : : * @param write_back_len
911 : : * The size of the write back length.
912 : : * @return
913 : : * The pointer to the start of the write back data linked list.
914 : : */
915 : : static __rte_always_inline struct vhost_crypto_writeback_data *
916 : : prepare_write_back_data(struct vhost_virtqueue *vq,
917 : : struct vhost_crypto_data_req *vc_req,
918 : : struct vhost_crypto_desc *head_desc,
919 : : struct vhost_crypto_desc **cur_desc,
920 : : struct vhost_crypto_writeback_data **end_wb_data,
921 : : uint8_t *src,
922 : : uint32_t offset,
923 : : uint64_t write_back_len,
924 : : uint32_t max_n_descs)
925 : : __rte_requires_shared_capability(&vq->iotlb_lock)
926 : : {
927 : : struct vhost_crypto_writeback_data *wb_data, *head;
928 : : struct vhost_crypto_desc *desc = *cur_desc;
929 : : uint64_t dlen;
930 : : uint8_t *dst;
931 : : int ret;
932 : :
933 : 0 : ret = rte_mempool_get(vc_req->wb_pool, (void **)&head);
934 [ # # # # : 0 : if (unlikely(ret < 0)) {
# # # # #
# # # ]
935 : 0 : VC_LOG_ERR("no memory");
936 : 0 : goto error_exit;
937 : : }
938 : :
939 : 0 : wb_data = head;
940 : :
941 [ # # # # : 0 : if (likely(desc->len > offset)) {
# # # # #
# # # ]
942 : 0 : wb_data->src = src + offset;
943 : 0 : dlen = desc->len;
944 [ # # # # : 0 : dst = IOVA_TO_VVA(uint8_t *, vc_req->dev, vq,
# # # # #
# # # ]
945 : : desc->addr, &dlen, VHOST_ACCESS_RW);
946 [ # # # # : 0 : if (unlikely(!dst || dlen != desc->len)) {
# # # # #
# # # # #
# # # # #
# # # #
# ]
947 : 0 : VC_LOG_ERR("Failed to map descriptor");
948 : 0 : goto error_exit;
949 : : }
950 : :
951 : 0 : wb_data->dst = dst + offset;
952 : 0 : wb_data->len = RTE_MIN(dlen - offset, write_back_len);
953 : 0 : write_back_len -= wb_data->len;
954 : 0 : src += offset + wb_data->len;
955 : : offset = 0;
956 : :
957 [ # # # # : 0 : if (unlikely(write_back_len)) {
# # # # #
# # # ]
958 : 0 : ret = rte_mempool_get(vc_req->wb_pool,
959 [ # # # # : 0 : (void **)&(wb_data->next));
# # # # #
# # # ]
960 [ # # # # : 0 : if (unlikely(ret < 0)) {
# # # # #
# # # ]
961 : 0 : VC_LOG_ERR("no memory");
962 : 0 : goto error_exit;
963 : : }
964 : :
965 : 0 : wb_data = wb_data->next;
966 : : } else
967 : 0 : wb_data->next = NULL;
968 : : } else
969 : 0 : offset -= desc->len;
970 : :
971 : 0 : while (write_back_len &&
972 [ # # # # : 0 : desc >= head_desc &&
# # # # #
# # # ]
973 [ # # # # : 0 : desc - head_desc < (int)max_n_descs) {
# # # # #
# # # ]
974 : 0 : desc++;
975 [ # # # # : 0 : if (unlikely(!(desc->flags & VRING_DESC_F_WRITE))) {
# # # # #
# # # ]
976 : 0 : VC_LOG_ERR("incorrect descriptor");
977 : 0 : goto error_exit;
978 : : }
979 : :
980 [ # # # # : 0 : if (desc->len <= offset) {
# # # # #
# # # ]
981 : 0 : offset -= desc->len;
982 : 0 : continue;
983 : : }
984 : :
985 : 0 : dlen = desc->len;
986 : 0 : dst = IOVA_TO_VVA(uint8_t *, vc_req->dev, vq,
987 [ # # # # : 0 : desc->addr, &dlen, VHOST_ACCESS_RW) + offset;
# # # # #
# # # ]
988 [ # # # # : 0 : if (unlikely(dst == NULL || dlen != desc->len)) {
# # # # #
# # # # #
# # # # #
# # # #
# ]
989 : 0 : VC_LOG_ERR("Failed to map descriptor");
990 : 0 : goto error_exit;
991 : : }
992 : :
993 : 0 : wb_data->src = src + offset;
994 : 0 : wb_data->dst = dst;
995 : 0 : wb_data->len = RTE_MIN(desc->len - offset, write_back_len);
996 : 0 : write_back_len -= wb_data->len;
997 : 0 : src += wb_data->len;
998 : : offset = 0;
999 : :
1000 [ # # # # : 0 : if (write_back_len) {
# # # # #
# # # ]
1001 : 0 : ret = rte_mempool_get(vc_req->wb_pool,
1002 [ # # # # : 0 : (void **)&(wb_data->next));
# # # # #
# # # ]
1003 [ # # # # : 0 : if (unlikely(ret < 0)) {
# # # # #
# # # ]
1004 : 0 : VC_LOG_ERR("no memory");
1005 : 0 : goto error_exit;
1006 : : }
1007 : :
1008 : 0 : wb_data = wb_data->next;
1009 : : } else
1010 : 0 : wb_data->next = NULL;
1011 : : }
1012 : :
1013 [ # # # # : 0 : if (unlikely(desc - head_desc == (int)max_n_descs))
# # # # #
# # # ]
1014 : : *cur_desc = NULL;
1015 : : else
1016 : 0 : *cur_desc = desc + 1;
1017 : :
1018 : : *end_wb_data = wb_data;
1019 : :
1020 : 0 : return head;
1021 : :
1022 : 0 : error_exit:
1023 [ # # # # : 0 : if (head)
# # # # #
# # # ]
1024 : 0 : free_wb_data(head, vc_req->wb_pool);
1025 : :
1026 : : return NULL;
1027 : : }
1028 : :
1029 : : static __rte_always_inline uint8_t
1030 : : vhost_crypto_check_cipher_request(struct virtio_crypto_cipher_data_req *req)
1031 : : {
1032 [ # # # # : 0 : if (likely((req->para.iv_len <= VHOST_CRYPTO_MAX_IV_LEN) &&
# # # # #
# # # ]
1033 : : (req->para.src_data_len <= RTE_MBUF_DEFAULT_BUF_SIZE) &&
1034 : : (req->para.dst_data_len >= req->para.src_data_len) &&
1035 : : (req->para.dst_data_len <= RTE_MBUF_DEFAULT_BUF_SIZE)))
1036 : 0 : return VIRTIO_CRYPTO_OK;
1037 : : return VIRTIO_CRYPTO_BADMSG;
1038 : : }
1039 : :
1040 : : static __rte_always_inline uint8_t
1041 : : prepare_sym_cipher_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
1042 : : struct vhost_virtqueue *vq,
1043 : : struct vhost_crypto_data_req *vc_req,
1044 : : struct virtio_crypto_cipher_data_req *cipher,
1045 : : struct vhost_crypto_desc *head,
1046 : : uint32_t max_n_descs)
1047 : : __rte_requires_shared_capability(&vq->iotlb_lock)
1048 : : {
1049 : : struct vhost_crypto_desc *desc = head;
1050 : : struct vhost_crypto_writeback_data *ewb = NULL;
1051 : 0 : struct rte_mbuf *m_src = op->sym->m_src, *m_dst = op->sym->m_dst;
1052 : 0 : uint8_t *iv_data = rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET);
1053 : : uint8_t ret = vhost_crypto_check_cipher_request(cipher);
1054 : :
1055 [ # # # # ]: 0 : if (unlikely(ret != VIRTIO_CRYPTO_OK))
1056 : 0 : goto error_exit;
1057 : :
1058 : : /* prepare */
1059 : : /* iv */
1060 [ # # # # ]: 0 : if (unlikely(copy_data(iv_data, vcrypto->dev, vq, head, &desc,
1061 : : cipher->para.iv_len, max_n_descs))) {
1062 : 0 : VC_LOG_ERR("Incorrect virtio descriptor");
1063 : : ret = VIRTIO_CRYPTO_BADMSG;
1064 : 0 : goto error_exit;
1065 : : }
1066 : :
1067 [ # # # # : 0 : switch (vcrypto->option) {
# # ]
1068 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
1069 : 0 : m_src->data_len = cipher->para.src_data_len;
1070 : 0 : rte_mbuf_iova_set(m_src,
1071 [ # # # # ]: 0 : gpa_to_hpa(vcrypto->dev, desc->addr, cipher->para.src_data_len));
1072 : 0 : m_src->buf_addr = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RO);
1073 [ # # # # : 0 : if (unlikely(rte_mbuf_iova_get(m_src) == 0 || m_src->buf_addr == NULL)) {
# # # # ]
1074 : 0 : VC_LOG_ERR("zero_copy may fail due to cross page data");
1075 : : ret = VIRTIO_CRYPTO_ERR;
1076 : 0 : goto error_exit;
1077 : : }
1078 : :
1079 [ # # # # ]: 0 : if (unlikely(move_desc(head, &desc, cipher->para.src_data_len,
1080 : : max_n_descs) < 0)) {
1081 : 0 : VC_LOG_ERR("Incorrect descriptor");
1082 : : ret = VIRTIO_CRYPTO_ERR;
1083 : 0 : goto error_exit;
1084 : : }
1085 : :
1086 : : break;
1087 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
1088 : 0 : vc_req->wb_pool = vcrypto->wb_pool;
1089 : 0 : m_src->data_len = cipher->para.src_data_len;
1090 [ # # # # ]: 0 : if (unlikely(copy_data(rte_pktmbuf_mtod(m_src, uint8_t *),
1091 : : vcrypto->dev, vq, head, &desc,
1092 : : cipher->para.src_data_len, max_n_descs) < 0)) {
1093 : 0 : VC_LOG_ERR("Incorrect virtio descriptor");
1094 : : ret = VIRTIO_CRYPTO_BADMSG;
1095 : 0 : goto error_exit;
1096 : : }
1097 : : break;
1098 : 0 : default:
1099 : : ret = VIRTIO_CRYPTO_BADMSG;
1100 : 0 : goto error_exit;
1101 : : }
1102 : :
1103 : : /* dst */
1104 : : desc = find_write_desc(head, desc, max_n_descs);
1105 [ # # # # ]: 0 : if (unlikely(!desc)) {
1106 : 0 : VC_LOG_ERR("Cannot find write location");
1107 : : ret = VIRTIO_CRYPTO_BADMSG;
1108 : 0 : goto error_exit;
1109 : : }
1110 : :
1111 [ # # # # : 0 : switch (vcrypto->option) {
# # ]
1112 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
1113 : 0 : rte_mbuf_iova_set(m_dst,
1114 [ # # # # ]: 0 : gpa_to_hpa(vcrypto->dev, desc->addr, cipher->para.dst_data_len));
1115 : 0 : m_dst->buf_addr = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RW);
1116 [ # # # # : 0 : if (unlikely(rte_mbuf_iova_get(m_dst) == 0 || m_dst->buf_addr == NULL)) {
# # # # ]
1117 : 0 : VC_LOG_ERR("zero_copy may fail due to cross page data");
1118 : : ret = VIRTIO_CRYPTO_ERR;
1119 : 0 : goto error_exit;
1120 : : }
1121 : :
1122 [ # # # # ]: 0 : if (unlikely(move_desc(head, &desc, cipher->para.dst_data_len,
1123 : : max_n_descs) < 0)) {
1124 : 0 : VC_LOG_ERR("Incorrect descriptor");
1125 : : ret = VIRTIO_CRYPTO_ERR;
1126 : 0 : goto error_exit;
1127 : : }
1128 : :
1129 : 0 : m_dst->data_len = cipher->para.dst_data_len;
1130 : 0 : break;
1131 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
1132 : 0 : vc_req->wb = prepare_write_back_data(vq, vc_req, head, &desc, &ewb,
1133 : 0 : rte_pktmbuf_mtod(m_src, uint8_t *), 0,
1134 [ # # # # ]: 0 : cipher->para.dst_data_len, max_n_descs);
1135 [ # # # # ]: 0 : if (unlikely(vc_req->wb == NULL)) {
1136 : : ret = VIRTIO_CRYPTO_ERR;
1137 : 0 : goto error_exit;
1138 : : }
1139 : :
1140 : : break;
1141 : 0 : default:
1142 : : ret = VIRTIO_CRYPTO_BADMSG;
1143 : 0 : goto error_exit;
1144 : : }
1145 : :
1146 : : /* src data */
1147 : 0 : op->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1148 : 0 : op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
1149 : :
1150 : 0 : op->sym->cipher.data.offset = 0;
1151 [ # # # # ]: 0 : op->sym->cipher.data.length = cipher->para.src_data_len;
1152 : :
1153 : 0 : vc_req->inhdr = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_WO);
1154 [ # # # # ]: 0 : if (unlikely(vc_req->inhdr == NULL)) {
1155 : : ret = VIRTIO_CRYPTO_BADMSG;
1156 : 0 : goto error_exit;
1157 : : }
1158 : :
1159 : 0 : vc_req->inhdr->status = VIRTIO_CRYPTO_OK;
1160 : 0 : vc_req->len = cipher->para.dst_data_len + INHDR_LEN;
1161 : :
1162 : 0 : return 0;
1163 : :
1164 : 0 : error_exit:
1165 [ # # # # ]: 0 : if (vc_req->wb)
1166 : 0 : free_wb_data(vc_req->wb, vc_req->wb_pool);
1167 : :
1168 : 0 : vc_req->len = INHDR_LEN;
1169 : 0 : return ret;
1170 : : }
1171 : :
1172 : : static __rte_always_inline uint8_t
1173 : : vhost_crypto_check_chain_request(struct virtio_crypto_alg_chain_data_req *req)
1174 : : {
1175 [ # # # # : 0 : if (likely((req->para.iv_len <= VHOST_CRYPTO_MAX_IV_LEN) &&
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
1176 : : (req->para.src_data_len <= VHOST_CRYPTO_MAX_DATA_SIZE) &&
1177 : : (req->para.dst_data_len >= req->para.src_data_len) &&
1178 : : (req->para.dst_data_len <= VHOST_CRYPTO_MAX_DATA_SIZE) &&
1179 : : (req->para.cipher_start_src_offset <
1180 : : VHOST_CRYPTO_MAX_DATA_SIZE) &&
1181 : : (req->para.len_to_cipher <= VHOST_CRYPTO_MAX_DATA_SIZE) &&
1182 : : (req->para.hash_start_src_offset <
1183 : : VHOST_CRYPTO_MAX_DATA_SIZE) &&
1184 : : (req->para.len_to_hash <= VHOST_CRYPTO_MAX_DATA_SIZE) &&
1185 : : (req->para.cipher_start_src_offset + req->para.len_to_cipher <=
1186 : : req->para.src_data_len) &&
1187 : : (req->para.hash_start_src_offset + req->para.len_to_hash <=
1188 : : req->para.src_data_len) &&
1189 : : (req->para.dst_data_len + req->para.hash_result_len <=
1190 : : VHOST_CRYPTO_MAX_DATA_SIZE)))
1191 : 0 : return VIRTIO_CRYPTO_OK;
1192 : : return VIRTIO_CRYPTO_BADMSG;
1193 : : }
1194 : :
1195 : : static __rte_always_inline uint8_t
1196 : : prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
1197 : : struct vhost_virtqueue *vq,
1198 : : struct vhost_crypto_data_req *vc_req,
1199 : : struct virtio_crypto_alg_chain_data_req *chain,
1200 : : struct vhost_crypto_desc *head,
1201 : : uint32_t max_n_descs)
1202 : : __rte_requires_shared_capability(&vq->iotlb_lock)
1203 : : {
1204 : : struct vhost_crypto_desc *desc = head, *digest_desc;
1205 : : struct vhost_crypto_writeback_data *ewb = NULL, *ewb2 = NULL;
1206 : 0 : struct rte_mbuf *m_src = op->sym->m_src, *m_dst = op->sym->m_dst;
1207 : 0 : uint8_t *iv_data = rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET);
1208 : : uint32_t digest_offset;
1209 : : void *digest_addr;
1210 : : uint8_t ret = vhost_crypto_check_chain_request(chain);
1211 : :
1212 [ # # # # ]: 0 : if (unlikely(ret != VIRTIO_CRYPTO_OK))
1213 : 0 : goto error_exit;
1214 : :
1215 : : /* prepare */
1216 : : /* iv */
1217 [ # # # # ]: 0 : if (unlikely(copy_data(iv_data, vcrypto->dev, vq, head, &desc,
1218 : : chain->para.iv_len, max_n_descs) < 0)) {
1219 : 0 : VC_LOG_ERR("Incorrect virtio descriptor");
1220 : : ret = VIRTIO_CRYPTO_BADMSG;
1221 : 0 : goto error_exit;
1222 : : }
1223 : :
1224 [ # # # # : 0 : switch (vcrypto->option) {
# # ]
1225 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
1226 : 0 : m_src->data_len = chain->para.src_data_len;
1227 : 0 : m_dst->data_len = chain->para.dst_data_len;
1228 : :
1229 : 0 : rte_mbuf_iova_set(m_src,
1230 [ # # # # ]: 0 : gpa_to_hpa(vcrypto->dev, desc->addr, chain->para.src_data_len));
1231 : 0 : m_src->buf_addr = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RO);
1232 [ # # # # : 0 : if (unlikely(rte_mbuf_iova_get(m_src) == 0 || m_src->buf_addr == NULL)) {
# # # # ]
1233 : 0 : VC_LOG_ERR("zero_copy may fail due to cross page data");
1234 : : ret = VIRTIO_CRYPTO_ERR;
1235 : 0 : goto error_exit;
1236 : : }
1237 : :
1238 [ # # # # ]: 0 : if (unlikely(move_desc(head, &desc, chain->para.src_data_len,
1239 : : max_n_descs) < 0)) {
1240 : 0 : VC_LOG_ERR("Incorrect descriptor");
1241 : : ret = VIRTIO_CRYPTO_ERR;
1242 : 0 : goto error_exit;
1243 : : }
1244 : : break;
1245 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
1246 : 0 : vc_req->wb_pool = vcrypto->wb_pool;
1247 : 0 : m_src->data_len = chain->para.src_data_len;
1248 [ # # # # ]: 0 : if (unlikely(copy_data(rte_pktmbuf_mtod(m_src, uint8_t *),
1249 : : vcrypto->dev, vq, head, &desc,
1250 : : chain->para.src_data_len, max_n_descs) < 0)) {
1251 : 0 : VC_LOG_ERR("Incorrect virtio descriptor");
1252 : : ret = VIRTIO_CRYPTO_BADMSG;
1253 : 0 : goto error_exit;
1254 : : }
1255 : :
1256 : : break;
1257 : 0 : default:
1258 : : ret = VIRTIO_CRYPTO_BADMSG;
1259 : 0 : goto error_exit;
1260 : : }
1261 : :
1262 : : /* dst */
1263 : : desc = find_write_desc(head, desc, max_n_descs);
1264 [ # # # # ]: 0 : if (unlikely(!desc)) {
1265 : 0 : VC_LOG_ERR("Cannot find write location");
1266 : : ret = VIRTIO_CRYPTO_BADMSG;
1267 : 0 : goto error_exit;
1268 : : }
1269 : :
1270 [ # # # # : 0 : switch (vcrypto->option) {
# # ]
1271 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
1272 : 0 : rte_mbuf_iova_set(m_dst,
1273 [ # # # # ]: 0 : gpa_to_hpa(vcrypto->dev, desc->addr, chain->para.dst_data_len));
1274 : 0 : m_dst->buf_addr = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RW);
1275 [ # # # # : 0 : if (unlikely(rte_mbuf_iova_get(m_dst) == 0 || m_dst->buf_addr == NULL)) {
# # # # ]
1276 : 0 : VC_LOG_ERR("zero_copy may fail due to cross page data");
1277 : : ret = VIRTIO_CRYPTO_ERR;
1278 : 0 : goto error_exit;
1279 : : }
1280 : :
1281 [ # # # # ]: 0 : if (unlikely(move_desc(vc_req->head, &desc,
1282 : : chain->para.dst_data_len, max_n_descs) < 0)) {
1283 : 0 : VC_LOG_ERR("Incorrect descriptor");
1284 : : ret = VIRTIO_CRYPTO_ERR;
1285 : 0 : goto error_exit;
1286 : : }
1287 : :
1288 [ # # # # ]: 0 : op->sym->auth.digest.phys_addr = gpa_to_hpa(vcrypto->dev,
1289 [ # # # # ]: 0 : desc->addr, chain->para.hash_result_len);
1290 : 0 : op->sym->auth.digest.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RW);
1291 [ # # # # ]: 0 : if (unlikely(op->sym->auth.digest.phys_addr == 0)) {
1292 : 0 : VC_LOG_ERR("zero_copy may fail due to cross page data");
1293 : : ret = VIRTIO_CRYPTO_ERR;
1294 : 0 : goto error_exit;
1295 : : }
1296 : :
1297 [ # # # # ]: 0 : if (unlikely(move_desc(head, &desc,
1298 : : chain->para.hash_result_len,
1299 : : max_n_descs) < 0)) {
1300 : 0 : VC_LOG_ERR("Incorrect descriptor");
1301 : : ret = VIRTIO_CRYPTO_ERR;
1302 : 0 : goto error_exit;
1303 : : }
1304 : :
1305 : : break;
1306 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
1307 : 0 : vc_req->wb = prepare_write_back_data(vq, vc_req, head, &desc, &ewb,
1308 : 0 : rte_pktmbuf_mtod(m_src, uint8_t *),
1309 : : chain->para.cipher_start_src_offset,
1310 : 0 : chain->para.dst_data_len -
1311 [ # # # # ]: 0 : chain->para.cipher_start_src_offset,
1312 : : max_n_descs);
1313 [ # # # # ]: 0 : if (unlikely(vc_req->wb == NULL)) {
1314 : : ret = VIRTIO_CRYPTO_ERR;
1315 : 0 : goto error_exit;
1316 : : }
1317 : :
1318 : : digest_desc = desc;
1319 : 0 : digest_offset = m_src->data_len;
1320 : 0 : digest_addr = rte_pktmbuf_mtod_offset(m_src, void *,
1321 : : digest_offset);
1322 : :
1323 : : /** create a wb_data for digest */
1324 : 0 : ewb->next = prepare_write_back_data(vq, vc_req, head, &desc,
1325 : : &ewb2, digest_addr, 0,
1326 [ # # # # ]: 0 : chain->para.hash_result_len, max_n_descs);
1327 [ # # # # ]: 0 : if (unlikely(ewb->next == NULL)) {
1328 : : ret = VIRTIO_CRYPTO_ERR;
1329 : 0 : goto error_exit;
1330 : : }
1331 : :
1332 [ # # # # ]: 0 : if (unlikely(copy_data(digest_addr, vcrypto->dev, vq, head,
1333 : : &digest_desc, chain->para.hash_result_len,
1334 : : max_n_descs) < 0)) {
1335 : 0 : VC_LOG_ERR("Incorrect virtio descriptor");
1336 : : ret = VIRTIO_CRYPTO_BADMSG;
1337 : 0 : goto error_exit;
1338 : : }
1339 : :
1340 : 0 : op->sym->auth.digest.data = digest_addr;
1341 : 0 : op->sym->auth.digest.phys_addr = rte_pktmbuf_iova_offset(m_src,
1342 : : digest_offset);
1343 : 0 : break;
1344 : 0 : default:
1345 : : ret = VIRTIO_CRYPTO_BADMSG;
1346 : 0 : goto error_exit;
1347 : : }
1348 : :
1349 : : /* record inhdr */
1350 : 0 : vc_req->inhdr = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_WO);
1351 [ # # # # ]: 0 : if (unlikely(vc_req->inhdr == NULL)) {
1352 : : ret = VIRTIO_CRYPTO_BADMSG;
1353 : 0 : goto error_exit;
1354 : : }
1355 : :
1356 : 0 : vc_req->inhdr->status = VIRTIO_CRYPTO_OK;
1357 : :
1358 : 0 : op->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1359 : 0 : op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
1360 : :
1361 : 0 : op->sym->cipher.data.offset = chain->para.cipher_start_src_offset;
1362 : 0 : op->sym->cipher.data.length = chain->para.src_data_len -
1363 : : chain->para.cipher_start_src_offset;
1364 : :
1365 : 0 : op->sym->auth.data.offset = chain->para.hash_start_src_offset;
1366 : 0 : op->sym->auth.data.length = chain->para.len_to_hash;
1367 : :
1368 : 0 : vc_req->len = chain->para.dst_data_len + chain->para.hash_result_len +
1369 : : INHDR_LEN;
1370 : 0 : return 0;
1371 : :
1372 : 0 : error_exit:
1373 [ # # # # ]: 0 : if (vc_req->wb)
1374 : 0 : free_wb_data(vc_req->wb, vc_req->wb_pool);
1375 : 0 : vc_req->len = INHDR_LEN;
1376 : 0 : return ret;
1377 : : }
1378 : :
1379 : : static __rte_always_inline uint8_t
1380 : : prepare_asym_rsa_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
1381 : : struct vhost_virtqueue *vq,
1382 : : struct vhost_crypto_data_req *vc_req,
1383 : : struct virtio_crypto_op_data_req *req,
1384 : : struct vhost_crypto_desc *head,
1385 : : uint32_t max_n_descs)
1386 : : __rte_requires_shared_capability(&vq->iotlb_lock)
1387 : : {
1388 : : struct rte_crypto_rsa_op_param *rsa = &op->asym->rsa;
1389 : : struct vhost_crypto_desc *desc = head;
1390 : : uint8_t ret = VIRTIO_CRYPTO_ERR;
1391 : : uint16_t wlen = 0;
1392 : :
1393 : : /* prepare */
1394 : 0 : switch (vcrypto->option) {
1395 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
1396 : 0 : vc_req->wb_pool = vcrypto->wb_pool;
1397 [ # # # # ]: 0 : if (req->header.opcode == VIRTIO_CRYPTO_AKCIPHER_SIGN) {
1398 [ # # # # ]: 0 : rsa->op_type = RTE_CRYPTO_ASYM_OP_SIGN;
1399 : 0 : rsa->message.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RO);
1400 : 0 : rsa->message.length = req->u.akcipher_req.para.src_data_len;
1401 : 0 : rsa->sign.length = req->u.akcipher_req.para.dst_data_len;
1402 : 0 : wlen = rsa->sign.length;
1403 : : desc = find_write_desc(head, desc, max_n_descs);
1404 [ # # # # ]: 0 : if (unlikely(!desc)) {
1405 : 0 : VC_LOG_ERR("Cannot find write location");
1406 : : ret = VIRTIO_CRYPTO_BADMSG;
1407 : 0 : goto error_exit;
1408 : : }
1409 : :
1410 : 0 : rsa->sign.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RW);
1411 [ # # # # ]: 0 : if (unlikely(rsa->sign.data == NULL)) {
1412 : : ret = VIRTIO_CRYPTO_ERR;
1413 : 0 : goto error_exit;
1414 : : }
1415 : :
1416 : 0 : desc += 1;
1417 [ # # # # ]: 0 : } else if (req->header.opcode == VIRTIO_CRYPTO_AKCIPHER_VERIFY) {
1418 [ # # # # ]: 0 : rsa->op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
1419 : 0 : rsa->sign.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RO);
1420 [ # # # # ]: 0 : rsa->sign.length = req->u.akcipher_req.para.src_data_len;
1421 : : desc += 1;
1422 : 0 : rsa->message.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RO);
1423 : 0 : rsa->message.length = req->u.akcipher_req.para.dst_data_len;
1424 : 0 : desc += 1;
1425 [ # # # # ]: 0 : } else if (req->header.opcode == VIRTIO_CRYPTO_AKCIPHER_ENCRYPT) {
1426 [ # # # # ]: 0 : rsa->op_type = RTE_CRYPTO_ASYM_OP_ENCRYPT;
1427 : 0 : rsa->message.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RO);
1428 : 0 : rsa->message.length = req->u.akcipher_req.para.src_data_len;
1429 : 0 : rsa->cipher.length = req->u.akcipher_req.para.dst_data_len;
1430 : 0 : wlen = rsa->cipher.length;
1431 : : desc = find_write_desc(head, desc, max_n_descs);
1432 [ # # # # ]: 0 : if (unlikely(!desc)) {
1433 : 0 : VC_LOG_ERR("Cannot find write location");
1434 : : ret = VIRTIO_CRYPTO_BADMSG;
1435 : 0 : goto error_exit;
1436 : : }
1437 : :
1438 : 0 : rsa->cipher.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RW);
1439 [ # # # # ]: 0 : if (unlikely(rsa->cipher.data == NULL)) {
1440 : : ret = VIRTIO_CRYPTO_ERR;
1441 : 0 : goto error_exit;
1442 : : }
1443 : :
1444 : 0 : desc += 1;
1445 : : } else if (req->header.opcode == VIRTIO_CRYPTO_AKCIPHER_DECRYPT) {
1446 [ # # # # ]: 0 : rsa->op_type = RTE_CRYPTO_ASYM_OP_DECRYPT;
1447 : 0 : rsa->cipher.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RO);
1448 [ # # # # ]: 0 : rsa->cipher.length = req->u.akcipher_req.para.src_data_len;
1449 : : desc += 1;
1450 : 0 : rsa->message.data = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_RO);
1451 : 0 : rsa->message.length = req->u.akcipher_req.para.dst_data_len;
1452 : 0 : desc += 1;
1453 : : } else {
1454 : : goto error_exit;
1455 : : }
1456 : : break;
1457 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
1458 : : default:
1459 : : ret = VIRTIO_CRYPTO_BADMSG;
1460 : 0 : goto error_exit;
1461 : : }
1462 : :
1463 : 0 : op->type = RTE_CRYPTO_OP_TYPE_ASYMMETRIC;
1464 [ # # # # ]: 0 : op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
1465 : :
1466 : 0 : vc_req->inhdr = get_data_ptr(vq, vc_req, desc, VHOST_ACCESS_WO);
1467 [ # # # # ]: 0 : if (unlikely(vc_req->inhdr == NULL)) {
1468 : : ret = VIRTIO_CRYPTO_BADMSG;
1469 : 0 : goto error_exit;
1470 : : }
1471 : :
1472 : 0 : vc_req->inhdr->status = VIRTIO_CRYPTO_OK;
1473 : 0 : vc_req->len = wlen + INHDR_LEN;
1474 : 0 : return 0;
1475 : 0 : error_exit:
1476 [ # # # # ]: 0 : if (vc_req->wb)
1477 : 0 : free_wb_data(vc_req->wb, vc_req->wb_pool);
1478 : :
1479 : 0 : vc_req->len = INHDR_LEN;
1480 : 0 : return ret;
1481 : : }
1482 : :
1483 : : /**
1484 : : * Process on descriptor
1485 : : */
1486 : : static __rte_always_inline int
1487 : : vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,
1488 : : struct vhost_virtqueue *vq, struct rte_crypto_op *op,
1489 : : struct vring_desc *head, struct vhost_crypto_desc *descs,
1490 : : uint16_t desc_idx)
1491 : : __rte_requires_shared_capability(&vq->iotlb_lock)
1492 : : {
1493 : : struct vhost_crypto_data_req *vc_req, *vc_req_out;
1494 : : struct rte_cryptodev_asym_session *asym_session;
1495 : : struct rte_cryptodev_sym_session *sym_session;
1496 : : struct vhost_crypto_session *vhost_session;
1497 : : struct vhost_crypto_desc *desc = descs;
1498 : : uint32_t nb_descs = 0, max_n_descs, i;
1499 : : struct vhost_crypto_data_req data_req;
1500 : : struct virtio_crypto_op_data_req req;
1501 : : struct virtio_crypto_inhdr *inhdr;
1502 : : struct vring_desc *src_desc;
1503 : : uint64_t session_id;
1504 : : uint64_t dlen;
1505 : : int err;
1506 : :
1507 : : vc_req = &data_req;
1508 : 0 : vc_req->desc_idx = desc_idx;
1509 : 0 : vc_req->dev = vcrypto->dev;
1510 : 0 : vc_req->vq = vq;
1511 : :
1512 : 0 : if (unlikely((head->flags & VRING_DESC_F_INDIRECT) == 0)) {
1513 : 0 : VC_LOG_ERR("Invalid descriptor");
1514 : 0 : return -1;
1515 : : }
1516 : :
1517 : 0 : dlen = head->len;
1518 [ # # # # ]: 0 : src_desc = IOVA_TO_VVA(struct vring_desc *, vc_req->dev, vq,
1519 : : head->addr, &dlen, VHOST_ACCESS_RO);
1520 [ # # # # : 0 : if (unlikely(!src_desc || dlen != head->len)) {
# # # # ]
1521 : 0 : VC_LOG_ERR("Invalid descriptor");
1522 : 0 : return -1;
1523 : : }
1524 : : head = src_desc;
1525 : :
1526 : 0 : nb_descs = max_n_descs = dlen / sizeof(struct vring_desc);
1527 [ # # # # ]: 0 : if (unlikely(nb_descs > VHOST_CRYPTO_MAX_N_DESC || nb_descs == 0)) {
1528 : : err = VIRTIO_CRYPTO_ERR;
1529 : 0 : VC_LOG_ERR("Cannot process num of descriptors %u", nb_descs);
1530 [ # # # # ]: 0 : if (nb_descs > 0) {
1531 : : struct vring_desc *inhdr_desc = head;
1532 [ # # # # ]: 0 : while (inhdr_desc->flags & VRING_DESC_F_NEXT) {
1533 [ # # # # ]: 0 : if (inhdr_desc->next >= max_n_descs)
1534 : : return -1;
1535 : 0 : inhdr_desc = &head[inhdr_desc->next];
1536 : : }
1537 [ # # # # ]: 0 : if (inhdr_desc->len != sizeof(*inhdr))
1538 : : return -1;
1539 [ # # # # ]: 0 : inhdr = IOVA_TO_VVA(struct virtio_crypto_inhdr *, vc_req->dev,
1540 : : vq, inhdr_desc->addr, &dlen,
1541 : : VHOST_ACCESS_WO);
1542 [ # # # # : 0 : if (unlikely(!inhdr || dlen != inhdr_desc->len))
# # # # ]
1543 : : return -1;
1544 : 0 : inhdr->status = VIRTIO_CRYPTO_ERR;
1545 : 0 : return -1;
1546 : : }
1547 : : }
1548 : :
1549 : : /* copy descriptors to local variable */
1550 [ # # # # ]: 0 : for (i = 0; i < max_n_descs; i++) {
1551 : 0 : desc->addr = src_desc->addr;
1552 : 0 : desc->len = src_desc->len;
1553 : 0 : desc->flags = src_desc->flags;
1554 : 0 : desc++;
1555 [ # # # # ]: 0 : if (unlikely((src_desc->flags & VRING_DESC_F_NEXT) == 0))
1556 : : break;
1557 [ # # # # ]: 0 : if (unlikely(src_desc->next >= max_n_descs)) {
1558 : : err = VIRTIO_CRYPTO_BADMSG;
1559 : 0 : VC_LOG_ERR("Invalid descriptor");
1560 : 0 : goto error_exit;
1561 : : }
1562 : 0 : src_desc = &head[src_desc->next];
1563 : : }
1564 : :
1565 : 0 : vc_req->head = head;
1566 : 0 : vc_req->zero_copy = vcrypto->option;
1567 : :
1568 : : nb_descs = desc - descs;
1569 : : desc = descs;
1570 : :
1571 [ # # # # ]: 0 : if (unlikely(desc->len < sizeof(req))) {
1572 : : err = VIRTIO_CRYPTO_BADMSG;
1573 : 0 : VC_LOG_ERR("Invalid descriptor");
1574 : 0 : goto error_exit;
1575 : : }
1576 : :
1577 [ # # # # ]: 0 : if (unlikely(copy_data(&req, vcrypto->dev, vq, descs, &desc, sizeof(req),
1578 : : max_n_descs) < 0)) {
1579 : : err = VIRTIO_CRYPTO_BADMSG;
1580 : 0 : VC_LOG_ERR("Invalid descriptor");
1581 : 0 : goto error_exit;
1582 : : }
1583 : :
1584 : : /* desc is advanced by 1 now */
1585 : : max_n_descs -= 1;
1586 : :
1587 [ # # # # : 0 : switch (req.header.opcode) {
# # ]
1588 : 0 : case VIRTIO_CRYPTO_CIPHER_ENCRYPT:
1589 : : case VIRTIO_CRYPTO_CIPHER_DECRYPT:
1590 [ # # # # ]: 0 : vc_req_out = rte_mbuf_to_priv(op->sym->m_src);
1591 : : memcpy(vc_req_out, vc_req, sizeof(struct vhost_crypto_data_req));
1592 : 0 : session_id = req.header.session_id;
1593 : :
1594 : : /* one branch to avoid unnecessary table lookup */
1595 [ # # # # ]: 0 : if (vcrypto->cache_sym_session_id != session_id) {
1596 : 0 : err = rte_hash_lookup_data(vcrypto->session_map,
1597 : : &session_id, (void **)&vhost_session);
1598 [ # # # # ]: 0 : if (unlikely(err < 0)) {
1599 : : err = VIRTIO_CRYPTO_ERR;
1600 : 0 : VC_LOG_ERR("Failed to find session %"PRIu64,
1601 : : session_id);
1602 : 0 : goto error_exit;
1603 : : }
1604 : :
1605 : 0 : vcrypto->cache_sym_session = vhost_session->sym;
1606 : 0 : vcrypto->cache_sym_session_id = session_id;
1607 : : }
1608 : :
1609 : 0 : sym_session = vcrypto->cache_sym_session;
1610 : 0 : op->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
1611 : :
1612 : 0 : err = rte_crypto_op_attach_sym_session(op, sym_session);
1613 [ # # # # ]: 0 : if (unlikely(err < 0)) {
1614 : : err = VIRTIO_CRYPTO_ERR;
1615 : 0 : VC_LOG_ERR("Failed to attach session to op");
1616 : 0 : goto error_exit;
1617 : : }
1618 : :
1619 [ # # # # : 0 : switch (req.u.sym_req.op_type) {
# # # # ]
1620 : 0 : case VIRTIO_CRYPTO_SYM_OP_NONE:
1621 : : err = VIRTIO_CRYPTO_NOTSUPP;
1622 : 0 : break;
1623 [ # # # # ]: 0 : case VIRTIO_CRYPTO_SYM_OP_CIPHER:
1624 : 0 : err = prepare_sym_cipher_op(vcrypto, op, vq, vc_req_out,
1625 : : &req.u.sym_req.u.cipher, desc,
1626 : : max_n_descs);
1627 : 0 : break;
1628 [ # # # # ]: 0 : case VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:
1629 : 0 : err = prepare_sym_chain_op(vcrypto, op, vq, vc_req_out,
1630 : : &req.u.sym_req.u.chain, desc,
1631 : : max_n_descs);
1632 : 0 : break;
1633 : : }
1634 [ # # # # ]: 0 : if (unlikely(err != 0)) {
1635 : 0 : VC_LOG_ERR("Failed to process sym request");
1636 : 0 : goto error_exit;
1637 : : }
1638 : : break;
1639 : 0 : case VIRTIO_CRYPTO_AKCIPHER_SIGN:
1640 : : case VIRTIO_CRYPTO_AKCIPHER_VERIFY:
1641 : : case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:
1642 : : case VIRTIO_CRYPTO_AKCIPHER_DECRYPT:
1643 : 0 : session_id = req.header.session_id;
1644 : :
1645 : : /* one branch to avoid unnecessary table lookup */
1646 [ # # # # ]: 0 : if (vcrypto->cache_asym_session_id != session_id) {
1647 : 0 : err = rte_hash_lookup_data(vcrypto->session_map,
1648 : : &session_id, (void **)&vhost_session);
1649 [ # # # # ]: 0 : if (unlikely(err < 0)) {
1650 : : err = VIRTIO_CRYPTO_ERR;
1651 : 0 : VC_LOG_ERR("Failed to find asym session %"PRIu64,
1652 : : session_id);
1653 : 0 : goto error_exit;
1654 : : }
1655 : :
1656 : 0 : vcrypto->cache_asym_session = vhost_session->asym;
1657 : 0 : vcrypto->cache_asym_session_id = session_id;
1658 : : }
1659 : :
1660 : 0 : asym_session = vcrypto->cache_asym_session;
1661 : 0 : op->type = RTE_CRYPTO_OP_TYPE_ASYMMETRIC;
1662 : :
1663 : 0 : err = rte_crypto_op_attach_asym_session(op, asym_session);
1664 [ # # # # ]: 0 : if (unlikely(err < 0)) {
1665 : : err = VIRTIO_CRYPTO_ERR;
1666 : 0 : VC_LOG_ERR("Failed to attach asym session to op");
1667 : 0 : goto error_exit;
1668 : : }
1669 : :
1670 : 0 : vc_req_out = rte_cryptodev_asym_session_get_user_data(asym_session);
1671 : : rte_memcpy(vc_req_out, vc_req, sizeof(struct vhost_crypto_data_req));
1672 : 0 : vc_req_out->wb = NULL;
1673 : :
1674 [ # # # # ]: 0 : switch (req.header.algo) {
1675 [ # # # # ]: 0 : case VIRTIO_CRYPTO_AKCIPHER_RSA:
1676 : 0 : err = prepare_asym_rsa_op(vcrypto, op, vq, vc_req_out,
1677 : : &req, desc, max_n_descs);
1678 : 0 : break;
1679 : : }
1680 [ # # # # ]: 0 : if (unlikely(err != 0)) {
1681 : 0 : VC_LOG_ERR("Failed to process asym request");
1682 : 0 : goto error_exit;
1683 : : }
1684 : :
1685 : : break;
1686 : 0 : default:
1687 : : err = VIRTIO_CRYPTO_ERR;
1688 : 0 : VC_LOG_ERR("Unsupported symmetric crypto request type %u",
1689 : : req.header.opcode);
1690 : 0 : goto error_exit;
1691 : : }
1692 : :
1693 : : return 0;
1694 : :
1695 [ # # # # ]: 0 : error_exit:
1696 : :
1697 : : inhdr = reach_inhdr(vc_req->dev, vq, descs, max_n_descs);
1698 [ # # # # ]: 0 : if (likely(inhdr != NULL))
1699 : 0 : inhdr->status = (uint8_t)err;
1700 : :
1701 : : return -1;
1702 : : }
1703 : :
1704 : : static __rte_always_inline struct vhost_virtqueue *
1705 : : vhost_crypto_finalize_one_request(struct rte_crypto_op *op,
1706 : : struct vhost_virtqueue *old_vq)
1707 : : {
1708 : : struct rte_mbuf *m_src = NULL, *m_dst = NULL;
1709 : : struct vhost_crypto_data_req *vc_req;
1710 : : struct vhost_virtqueue *vq;
1711 : : uint16_t used_idx, desc_idx;
1712 : :
1713 : 0 : if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
1714 : 0 : m_src = op->sym->m_src;
1715 : 0 : m_dst = op->sym->m_dst;
1716 : : vc_req = rte_mbuf_to_priv(m_src);
1717 [ # # # # ]: 0 : } else if (op->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
1718 : 0 : vc_req = rte_cryptodev_asym_session_get_user_data(op->asym->session);
1719 : : } else {
1720 : 0 : VC_LOG_ERR("Invalid crypto op type");
1721 : 0 : return NULL;
1722 : : }
1723 : :
1724 [ # # # # ]: 0 : if (unlikely(!vc_req)) {
1725 : 0 : VC_LOG_ERR("Failed to retrieve vc_req");
1726 : 0 : return NULL;
1727 : : }
1728 : 0 : vq = vc_req->vq;
1729 : 0 : used_idx = vc_req->desc_idx;
1730 : :
1731 [ # # ]: 0 : if (old_vq && (vq != old_vq))
1732 : : return vq;
1733 : :
1734 [ # # # # ]: 0 : if (unlikely(op->status != RTE_CRYPTO_OP_STATUS_SUCCESS))
1735 : 0 : vc_req->inhdr->status = VIRTIO_CRYPTO_ERR;
1736 : : else {
1737 [ # # # # ]: 0 : if (vc_req->zero_copy == 0)
1738 : 0 : write_back_data(vc_req);
1739 : : }
1740 : :
1741 : 0 : desc_idx = vq->avail->ring[used_idx];
1742 : 0 : vq->used->ring[desc_idx].id = vq->avail->ring[desc_idx];
1743 : 0 : vq->used->ring[desc_idx].len = vc_req->len;
1744 : :
1745 [ # # # # ]: 0 : if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
1746 [ # # # # ]: 0 : rte_mempool_put(m_src->pool, (void *)m_src);
1747 [ # # # # ]: 0 : if (m_dst)
1748 [ # # # # ]: 0 : rte_mempool_put(m_dst->pool, (void *)m_dst);
1749 : : }
1750 : :
1751 : : return vq;
1752 : : }
1753 : :
1754 : : static __rte_always_inline uint16_t
1755 : : vhost_crypto_complete_one_vm_requests(struct rte_crypto_op **ops,
1756 : : uint16_t nb_ops, int *callfd)
1757 : : {
1758 : : uint16_t processed = 1;
1759 : : struct vhost_virtqueue *vq, *tmp_vq;
1760 : :
1761 : : if (unlikely(nb_ops == 0))
1762 : : return 0;
1763 : :
1764 [ # # ]: 0 : vq = vhost_crypto_finalize_one_request(ops[0], NULL);
1765 [ # # ]: 0 : if (unlikely(vq == NULL))
1766 : : return 0;
1767 : : tmp_vq = vq;
1768 : :
1769 [ # # ]: 0 : while ((processed < nb_ops)) {
1770 [ # # ]: 0 : tmp_vq = vhost_crypto_finalize_one_request(ops[processed],
1771 : : tmp_vq);
1772 : :
1773 [ # # ]: 0 : if (unlikely(vq != tmp_vq))
1774 : : break;
1775 : :
1776 : 0 : processed++;
1777 : : }
1778 : :
1779 : 0 : *callfd = vq->callfd;
1780 : :
1781 : 0 : *(volatile uint16_t *)&vq->used->idx += processed;
1782 : :
1783 : 0 : return processed;
1784 : : }
1785 : :
1786 : : RTE_EXPORT_SYMBOL(rte_vhost_crypto_driver_start)
1787 : : int
1788 : 0 : rte_vhost_crypto_driver_start(const char *path)
1789 : : {
1790 : : uint64_t protocol_features;
1791 : : int ret;
1792 : :
1793 : 0 : ret = rte_vhost_driver_set_features(path, VIRTIO_CRYPTO_FEATURES);
1794 [ # # ]: 0 : if (ret)
1795 : : return -1;
1796 : :
1797 : 0 : ret = rte_vhost_driver_get_protocol_features(path, &protocol_features);
1798 [ # # ]: 0 : if (ret)
1799 : : return -1;
1800 : 0 : protocol_features |= (1ULL << VHOST_USER_PROTOCOL_F_CONFIG);
1801 : 0 : ret = rte_vhost_driver_set_protocol_features(path, protocol_features);
1802 [ # # ]: 0 : if (ret)
1803 : : return -1;
1804 : :
1805 : 0 : return rte_vhost_driver_start(path);
1806 : : }
1807 : :
1808 : : RTE_EXPORT_SYMBOL(rte_vhost_crypto_create)
1809 : : int
1810 [ # # ]: 0 : rte_vhost_crypto_create(int vid, uint8_t cryptodev_id,
1811 : : struct rte_mempool *sess_pool,
1812 : : int socket_id)
1813 : : {
1814 : : struct virtio_net *dev = get_device(vid);
1815 : 0 : struct rte_hash_parameters params = {0};
1816 : : struct vhost_crypto *vcrypto;
1817 : : char name[128];
1818 : : int ret;
1819 : :
1820 [ # # ]: 0 : if (!dev) {
1821 : 0 : VC_LOG_ERR("Invalid vid %i", vid);
1822 : 0 : return -EINVAL;
1823 : : }
1824 : :
1825 : 0 : vcrypto = rte_zmalloc_socket(NULL, sizeof(*vcrypto),
1826 : : RTE_CACHE_LINE_SIZE, socket_id);
1827 [ # # ]: 0 : if (!vcrypto) {
1828 : 0 : VC_LOG_ERR("Insufficient memory");
1829 : 0 : return -ENOMEM;
1830 : : }
1831 : :
1832 : 0 : vcrypto->sess_pool = sess_pool;
1833 : 0 : vcrypto->cid = cryptodev_id;
1834 : 0 : vcrypto->cache_sym_session_id = UINT64_MAX;
1835 : 0 : vcrypto->cache_asym_session_id = UINT64_MAX;
1836 : 0 : vcrypto->last_session_id = 1;
1837 : 0 : vcrypto->dev = dev;
1838 : 0 : vcrypto->option = RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE;
1839 : :
1840 : : snprintf(name, 127, "HASH_VHOST_CRYPT_%u", (uint32_t)vid);
1841 : 0 : params.name = name;
1842 : 0 : params.entries = VHOST_CRYPTO_SESSION_MAP_ENTRIES;
1843 : 0 : params.hash_func = rte_jhash;
1844 : 0 : params.key_len = sizeof(uint64_t);
1845 : 0 : params.socket_id = socket_id;
1846 : 0 : vcrypto->session_map = rte_hash_create(¶ms);
1847 [ # # ]: 0 : if (!vcrypto->session_map) {
1848 : 0 : VC_LOG_ERR("Failed to creath session map");
1849 : : ret = -ENOMEM;
1850 : 0 : goto error_exit;
1851 : : }
1852 : :
1853 : : snprintf(name, 127, "MBUF_POOL_VM_%u", (uint32_t)vid);
1854 : 0 : vcrypto->mbuf_pool = rte_pktmbuf_pool_create(name,
1855 : : VHOST_CRYPTO_MBUF_POOL_SIZE, 512,
1856 : : sizeof(struct vhost_crypto_data_req),
1857 : : VHOST_CRYPTO_MAX_DATA_SIZE + RTE_PKTMBUF_HEADROOM,
1858 : 0 : rte_socket_id());
1859 [ # # ]: 0 : if (!vcrypto->mbuf_pool) {
1860 : 0 : VC_LOG_ERR("Failed to creath mbuf pool");
1861 : : ret = -ENOMEM;
1862 : 0 : goto error_exit;
1863 : : }
1864 : :
1865 : : snprintf(name, 127, "WB_POOL_VM_%u", (uint32_t)vid);
1866 : 0 : vcrypto->wb_pool = rte_mempool_create(name,
1867 : : VHOST_CRYPTO_MBUF_POOL_SIZE,
1868 : : sizeof(struct vhost_crypto_writeback_data),
1869 : : 128, 0, NULL, NULL, NULL, NULL,
1870 : 0 : rte_socket_id(), 0);
1871 [ # # ]: 0 : if (!vcrypto->wb_pool) {
1872 : 0 : VC_LOG_ERR("Failed to creath mempool");
1873 : : ret = -ENOMEM;
1874 : 0 : goto error_exit;
1875 : : }
1876 : :
1877 : 0 : dev->extern_data = vcrypto;
1878 : 0 : dev->extern_ops.pre_msg_handle = NULL;
1879 : 0 : dev->extern_ops.post_msg_handle = vhost_crypto_msg_post_handler;
1880 : :
1881 : 0 : return 0;
1882 : :
1883 : 0 : error_exit:
1884 : 0 : rte_hash_free(vcrypto->session_map);
1885 : 0 : rte_mempool_free(vcrypto->mbuf_pool);
1886 : :
1887 : 0 : rte_free(vcrypto);
1888 : :
1889 : 0 : return ret;
1890 : : }
1891 : :
1892 : : RTE_EXPORT_SYMBOL(rte_vhost_crypto_free)
1893 : : int
1894 [ # # ]: 0 : rte_vhost_crypto_free(int vid)
1895 : : {
1896 : : struct virtio_net *dev = get_device(vid);
1897 : : struct vhost_crypto *vcrypto;
1898 : :
1899 [ # # ]: 0 : if (unlikely(dev == NULL)) {
1900 : 0 : VC_LOG_ERR("Invalid vid %i", vid);
1901 : 0 : return -EINVAL;
1902 : : }
1903 : :
1904 : 0 : vcrypto = dev->extern_data;
1905 [ # # ]: 0 : if (unlikely(vcrypto == NULL)) {
1906 : 0 : VC_LOG_ERR("Cannot find required data, is it initialized?");
1907 : 0 : return -ENOENT;
1908 : : }
1909 : :
1910 : 0 : rte_hash_free(vcrypto->session_map);
1911 : 0 : rte_mempool_free(vcrypto->mbuf_pool);
1912 : 0 : rte_mempool_free(vcrypto->wb_pool);
1913 : 0 : rte_free(vcrypto);
1914 : :
1915 : 0 : dev->extern_data = NULL;
1916 : 0 : dev->extern_ops.pre_msg_handle = NULL;
1917 : 0 : dev->extern_ops.post_msg_handle = NULL;
1918 : :
1919 : 0 : return 0;
1920 : : }
1921 : :
1922 : : RTE_EXPORT_SYMBOL(rte_vhost_crypto_set_zero_copy)
1923 : : int
1924 [ # # ]: 0 : rte_vhost_crypto_set_zero_copy(int vid, enum rte_vhost_crypto_zero_copy option)
1925 : : {
1926 : : struct virtio_net *dev = get_device(vid);
1927 : : struct vhost_crypto *vcrypto;
1928 : :
1929 [ # # ]: 0 : if (unlikely(dev == NULL)) {
1930 : 0 : VC_LOG_ERR("Invalid vid %i", vid);
1931 : 0 : return -EINVAL;
1932 : : }
1933 : :
1934 [ # # ]: 0 : if (unlikely((uint32_t)option >=
1935 : : RTE_VHOST_CRYPTO_MAX_ZERO_COPY_OPTIONS)) {
1936 : 0 : VC_LOG_ERR("Invalid option %i", option);
1937 : 0 : return -EINVAL;
1938 : : }
1939 : :
1940 : 0 : vcrypto = (struct vhost_crypto *)dev->extern_data;
1941 [ # # ]: 0 : if (unlikely(vcrypto == NULL)) {
1942 : 0 : VC_LOG_ERR("Cannot find required data, is it initialized?");
1943 : 0 : return -ENOENT;
1944 : : }
1945 : :
1946 [ # # ]: 0 : if (vcrypto->option == (uint8_t)option)
1947 : : return 0;
1948 : :
1949 [ # # # # ]: 0 : if (!(rte_mempool_full(vcrypto->mbuf_pool)) ||
1950 : 0 : !(rte_mempool_full(vcrypto->wb_pool))) {
1951 : 0 : VC_LOG_ERR("Cannot update zero copy as mempool is not full");
1952 : 0 : return -EINVAL;
1953 : : }
1954 : :
1955 [ # # ]: 0 : if (option == RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE) {
1956 : : char name[128];
1957 : :
1958 : : snprintf(name, 127, "WB_POOL_VM_%u", (uint32_t)vid);
1959 : 0 : vcrypto->wb_pool = rte_mempool_create(name,
1960 : : VHOST_CRYPTO_MBUF_POOL_SIZE,
1961 : : sizeof(struct vhost_crypto_writeback_data),
1962 : : 128, 0, NULL, NULL, NULL, NULL,
1963 : 0 : rte_socket_id(), 0);
1964 [ # # ]: 0 : if (!vcrypto->wb_pool) {
1965 : 0 : VC_LOG_ERR("Failed to creath mbuf pool");
1966 : 0 : return -ENOMEM;
1967 : : }
1968 : : } else {
1969 : 0 : rte_mempool_free(vcrypto->wb_pool);
1970 : 0 : vcrypto->wb_pool = NULL;
1971 : : }
1972 : :
1973 : 0 : vcrypto->option = (uint8_t)option;
1974 : :
1975 : 0 : return 0;
1976 : : }
1977 : :
1978 : : RTE_EXPORT_SYMBOL(rte_vhost_crypto_fetch_requests)
1979 : : uint16_t
1980 [ # # ]: 0 : rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,
1981 : : struct rte_crypto_op **ops, uint16_t nb_ops)
1982 : : {
1983 : : struct rte_mbuf *mbufs[VHOST_CRYPTO_MAX_BURST_SIZE * 2];
1984 : : struct vhost_crypto_desc descs[VHOST_CRYPTO_MAX_N_DESC];
1985 : : struct virtio_net *dev = get_device(vid);
1986 : : struct vhost_crypto *vcrypto;
1987 : : struct vhost_virtqueue *vq;
1988 : : uint16_t avail_idx;
1989 : : uint16_t start_idx;
1990 : : uint16_t count;
1991 : : uint16_t i = 0;
1992 : :
1993 [ # # ]: 0 : if (unlikely(dev == NULL)) {
1994 : 0 : VC_LOG_ERR("Invalid vid %i", vid);
1995 : 0 : return 0;
1996 : : }
1997 : :
1998 [ # # ]: 0 : if (unlikely(qid >= VHOST_MAX_QUEUE_PAIRS)) {
1999 : 0 : VC_LOG_ERR("Invalid qid %u", qid);
2000 : 0 : return 0;
2001 : : }
2002 : :
2003 : 0 : vcrypto = (struct vhost_crypto *)dev->extern_data;
2004 [ # # ]: 0 : if (unlikely(vcrypto == NULL)) {
2005 : 0 : VC_LOG_ERR("Cannot find required data, is it initialized?");
2006 : 0 : return 0;
2007 : : }
2008 : :
2009 : 0 : vq = dev->virtqueue[qid];
2010 : :
2011 [ # # ]: 0 : if (unlikely(vq == NULL)) {
2012 : 0 : VC_LOG_ERR("Invalid virtqueue %u", qid);
2013 : 0 : return 0;
2014 : : }
2015 : :
2016 [ # # ]: 0 : if (unlikely(rte_rwlock_read_trylock(&vq->access_lock) != 0))
2017 : : return 0;
2018 : :
2019 : : vhost_user_iotlb_rd_lock(vq);
2020 [ # # ]: 0 : if (unlikely(!vq->access_ok)) {
2021 : : VC_LOG_DBG("Virtqueue %u vrings not yet initialized", qid);
2022 : 0 : goto out_unlock;
2023 : : }
2024 : :
2025 : 0 : avail_idx = *((volatile uint16_t *)&vq->avail->idx);
2026 : 0 : start_idx = vq->last_used_idx;
2027 : 0 : count = avail_idx - start_idx;
2028 : 0 : count = RTE_MIN(count, VHOST_CRYPTO_MAX_BURST_SIZE);
2029 : 0 : count = RTE_MIN(count, nb_ops);
2030 : :
2031 [ # # ]: 0 : if (unlikely(count == 0))
2032 : 0 : goto out_unlock;
2033 : :
2034 : : /* for zero copy, we need 2 empty mbufs for src and dst, otherwise
2035 : : * we need only 1 mbuf as src and dst
2036 : : */
2037 [ # # # ]: 0 : switch (vcrypto->option) {
2038 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
2039 [ # # # # ]: 0 : if (unlikely(rte_mempool_get_bulk(vcrypto->mbuf_pool,
2040 : : (void **)mbufs, count * 2) < 0)) {
2041 : 0 : VC_LOG_ERR("Insufficient memory");
2042 : 0 : goto out_unlock;
2043 : : }
2044 : :
2045 [ # # ]: 0 : for (i = 0; i < count; i++) {
2046 : 0 : uint16_t used_idx = (start_idx + i) & (vq->size - 1);
2047 : 0 : uint16_t desc_idx = vq->avail->ring[used_idx];
2048 : 0 : struct vring_desc *head = &vq->desc[desc_idx];
2049 : 0 : struct rte_crypto_op *op = ops[i];
2050 : :
2051 : 0 : op->sym->m_src = mbufs[i * 2];
2052 : 0 : op->sym->m_dst = mbufs[i * 2 + 1];
2053 : 0 : op->sym->m_src->data_off = 0;
2054 [ # # ]: 0 : op->sym->m_dst->data_off = 0;
2055 : :
2056 [ # # ]: 0 : if (unlikely(vhost_crypto_process_one_req(vcrypto, vq,
2057 : : op, head, descs, used_idx) < 0))
2058 : : break;
2059 : : }
2060 : :
2061 [ # # ]: 0 : if (unlikely(i < count))
2062 : 0 : rte_mempool_put_bulk(vcrypto->mbuf_pool,
2063 : 0 : (void **)&mbufs[i * 2],
2064 [ # # ]: 0 : (count - i) * 2);
2065 : :
2066 : : break;
2067 : :
2068 : 0 : case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
2069 [ # # # # ]: 0 : if (unlikely(rte_mempool_get_bulk(vcrypto->mbuf_pool,
2070 : : (void **)mbufs, count) < 0)) {
2071 : 0 : VC_LOG_ERR("Insufficient memory");
2072 : 0 : goto out_unlock;
2073 : : }
2074 : :
2075 [ # # ]: 0 : for (i = 0; i < count; i++) {
2076 : 0 : uint16_t used_idx = (start_idx + i) & (vq->size - 1);
2077 : 0 : uint16_t desc_idx = vq->avail->ring[used_idx];
2078 : 0 : struct vring_desc *head = &vq->desc[desc_idx];
2079 : 0 : struct rte_crypto_op *op = ops[i];
2080 : :
2081 : 0 : op->sym->m_src = mbufs[i];
2082 : 0 : op->sym->m_dst = NULL;
2083 [ # # ]: 0 : op->sym->m_src->data_off = 0;
2084 : :
2085 [ # # ]: 0 : if (unlikely(vhost_crypto_process_one_req(vcrypto, vq,
2086 : : op, head, descs, desc_idx) < 0))
2087 : : break;
2088 : : }
2089 : :
2090 [ # # ]: 0 : if (unlikely(i < count))
2091 : 0 : rte_mempool_put_bulk(vcrypto->mbuf_pool,
2092 : 0 : (void **)&mbufs[i],
2093 [ # # ]: 0 : count - i);
2094 : :
2095 : : break;
2096 : :
2097 : : }
2098 : :
2099 : 0 : vq->last_used_idx += i;
2100 : :
2101 : 0 : out_unlock:
2102 : : vhost_user_iotlb_rd_unlock(vq);
2103 : 0 : rte_rwlock_read_unlock(&vq->access_lock);
2104 : :
2105 : 0 : return i;
2106 : : }
2107 : :
2108 : : RTE_EXPORT_SYMBOL(rte_vhost_crypto_finalize_requests)
2109 : : uint16_t
2110 : 0 : rte_vhost_crypto_finalize_requests(struct rte_crypto_op **ops,
2111 : : uint16_t nb_ops, int *callfds, uint16_t *nb_callfds)
2112 : : {
2113 : : struct rte_crypto_op **tmp_ops = ops;
2114 : : uint16_t count = 0, left = nb_ops;
2115 : : int callfd;
2116 : : uint16_t idx = 0;
2117 : :
2118 [ # # ]: 0 : while (left) {
2119 : : count = vhost_crypto_complete_one_vm_requests(tmp_ops, left,
2120 : : &callfd);
2121 [ # # ]: 0 : if (unlikely(count == 0))
2122 : : break;
2123 : :
2124 : 0 : tmp_ops = &tmp_ops[count];
2125 : 0 : left -= count;
2126 : :
2127 : 0 : callfds[idx++] = callfd;
2128 : :
2129 [ # # ]: 0 : if (unlikely(idx >= VIRTIO_CRYPTO_MAX_NUM_BURST_VQS)) {
2130 : 0 : VC_LOG_ERR("Too many vqs");
2131 : 0 : break;
2132 : : }
2133 : : }
2134 : :
2135 : 0 : *nb_callfds = idx;
2136 : :
2137 : 0 : return nb_ops - left;
2138 : : }
|