test/service: fix race condition on stopping lcore
[dpdk.git] / app / test / test_cryptodev_blockcipher.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2017 Intel Corporation
3  */
4
5 #include <rte_common.h>
6 #include <rte_hexdump.h>
7 #include <rte_mbuf.h>
8 #include <rte_malloc.h>
9 #include <rte_memcpy.h>
10 #include <rte_pause.h>
11
12 #include <rte_crypto.h>
13 #include <rte_cryptodev.h>
14 #include <rte_cryptodev_pmd.h>
15
16 #include "test.h"
17 #include "test_cryptodev.h"
18 #include "test_cryptodev_blockcipher.h"
19 #include "test_cryptodev_aes_test_vectors.h"
20 #include "test_cryptodev_des_test_vectors.h"
21 #include "test_cryptodev_hash_test_vectors.h"
22
23 static int
24 verify_algo_support(const struct blockcipher_test_case *t,
25                 const uint8_t dev_id, const uint32_t digest_len)
26 {
27         int ret = 0;
28         const struct blockcipher_test_data *tdata = t->test_data;
29         struct rte_cryptodev_sym_capability_idx cap_idx;
30         const struct rte_cryptodev_symmetric_capability *capability;
31
32         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
33                 cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
34                 cap_idx.algo.cipher = tdata->crypto_algo;
35                 capability = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
36                 if (capability == NULL)
37                         return -1;
38
39                 if (cap_idx.algo.cipher != RTE_CRYPTO_CIPHER_NULL)
40                         ret = rte_cryptodev_sym_capability_check_cipher(capability,
41                                                         tdata->cipher_key.len,
42                                                         tdata->iv.len);
43                 if (ret != 0)
44                         return -1;
45         }
46
47         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
48                 cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
49                 cap_idx.algo.auth = tdata->auth_algo;
50                 capability = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
51                 if (capability == NULL)
52                         return -1;
53
54                 if (cap_idx.algo.auth != RTE_CRYPTO_AUTH_NULL)
55                         ret = rte_cryptodev_sym_capability_check_auth(capability,
56                                                         tdata->auth_key.len,
57                                                         digest_len,
58                                                         0);
59                 if (ret != 0)
60                         return -1;
61         }
62
63         return 0;
64 }
65
66 static int
67 test_blockcipher_one_case(const struct blockcipher_test_case *t,
68         struct rte_mempool *mbuf_pool,
69         struct rte_mempool *op_mpool,
70         struct rte_mempool *sess_mpool,
71         struct rte_mempool *sess_priv_mpool,
72         uint8_t dev_id,
73         char *test_msg)
74 {
75         struct rte_mbuf *ibuf = NULL;
76         struct rte_mbuf *obuf = NULL;
77         struct rte_mbuf *iobuf;
78         struct rte_crypto_sym_xform *cipher_xform = NULL;
79         struct rte_crypto_sym_xform *auth_xform = NULL;
80         struct rte_crypto_sym_xform *init_xform = NULL;
81         struct rte_crypto_sym_op *sym_op = NULL;
82         struct rte_crypto_op *op = NULL;
83         struct rte_cryptodev_info dev_info;
84         struct rte_cryptodev_sym_session *sess = NULL;
85
86         int status = TEST_SUCCESS;
87         const struct blockcipher_test_data *tdata = t->test_data;
88         uint8_t cipher_key[tdata->cipher_key.len];
89         uint8_t auth_key[tdata->auth_key.len];
90         uint32_t buf_len = tdata->ciphertext.len;
91         uint32_t digest_len = tdata->digest.len;
92         char *buf_p = NULL;
93         uint8_t src_pattern = 0xa5;
94         uint8_t dst_pattern = 0xb6;
95         uint8_t tmp_src_buf[MBUF_SIZE];
96         uint8_t tmp_dst_buf[MBUF_SIZE];
97
98         int nb_segs = 1;
99         uint32_t nb_iterates = 0;
100
101         rte_cryptodev_info_get(dev_id, &dev_info);
102         uint64_t feat_flags = dev_info.feature_flags;
103
104         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
105                 if (!(feat_flags & RTE_CRYPTODEV_FF_SYM_SESSIONLESS)) {
106                         printf("Device doesn't support sesionless operations "
107                                 "Test Skipped.\n");
108                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
109                                 "SKIPPED");
110                         return TEST_SKIPPED;
111                 }
112         }
113         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
114                 uint64_t oop_flag = RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT;
115
116                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
117                         if (!(feat_flags & oop_flag)) {
118                                 printf("Device doesn't support out-of-place "
119                                         "scatter-gather in input mbuf. "
120                                         "Test Skipped.\n");
121                                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
122                                         "SKIPPED");
123                                 return TEST_SKIPPED;
124                         }
125                 } else {
126                         if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
127                                 printf("Device doesn't support in-place "
128                                         "scatter-gather mbufs. "
129                                         "Test Skipped.\n");
130                                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
131                                         "SKIPPED");
132                                 return TEST_SKIPPED;
133                         }
134                 }
135
136                 nb_segs = 3;
137         }
138
139         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
140                 uint64_t oop_flags = RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
141                         RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
142                         RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
143                         RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT;
144                 if (!(feat_flags & oop_flags)) {
145                         printf("Device doesn't support out-of-place operations."
146                                 "Test Skipped.\n");
147                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
148                                 "SKIPPED");
149                         return TEST_SKIPPED;
150                 }
151         }
152
153         if (tdata->cipher_key.len)
154                 memcpy(cipher_key, tdata->cipher_key.data,
155                         tdata->cipher_key.len);
156         if (tdata->auth_key.len)
157                 memcpy(auth_key, tdata->auth_key.data,
158                         tdata->auth_key.len);
159
160         /* Check if PMD is capable of performing that test */
161         if (verify_algo_support(t, dev_id, digest_len) < 0) {
162                 RTE_LOG(DEBUG, USER1,
163                         "Device does not support this algorithm."
164                         "Test Skipped.\n");
165                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "SKIPPED");
166                 return TEST_SKIPPED;
167         }
168
169         /* preparing data */
170         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
171                 buf_len += digest_len;
172
173         /* for contiguous mbuf, nb_segs is 1 */
174         ibuf = create_segmented_mbuf(mbuf_pool,
175                         tdata->ciphertext.len, nb_segs, src_pattern);
176         if (ibuf == NULL) {
177                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
178                         "line %u FAILED: %s",
179                         __LINE__, "Cannot create source mbuf");
180                 status = TEST_FAILED;
181                 goto error_exit;
182         }
183
184         /* only encryption requires plaintext.data input,
185          * decryption/(digest gen)/(digest verify) use ciphertext.data
186          * to be computed
187          */
188         if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
189                 pktmbuf_write(ibuf, 0, tdata->plaintext.len,
190                                 tdata->plaintext.data);
191         else
192                 pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
193                                 tdata->ciphertext.data);
194
195         buf_p = rte_pktmbuf_append(ibuf, digest_len);
196         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
197                 rte_memcpy(buf_p, tdata->digest.data, digest_len);
198         else
199                 memset(buf_p, 0, digest_len);
200
201         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
202                 obuf = rte_pktmbuf_alloc(mbuf_pool);
203                 if (!obuf) {
204                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
205                                 "FAILED: %s", __LINE__,
206                                 "Allocation of rte_mbuf failed");
207                         status = TEST_FAILED;
208                         goto error_exit;
209                 }
210                 memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
211
212                 buf_p = rte_pktmbuf_append(obuf, buf_len);
213                 if (!buf_p) {
214                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
215                                 "FAILED: %s", __LINE__,
216                                 "No room to append mbuf");
217                         status = TEST_FAILED;
218                         goto error_exit;
219                 }
220                 memset(buf_p, 0, buf_len);
221         }
222
223         /* Generate Crypto op data structure */
224         op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
225         if (!op) {
226                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
227                         "line %u FAILED: %s",
228                         __LINE__, "Failed to allocate symmetric crypto "
229                         "operation struct");
230                 status = TEST_FAILED;
231                 goto error_exit;
232         }
233
234         sym_op = op->sym;
235
236 iterate:
237         if (nb_iterates) {
238                 struct rte_mbuf *tmp_buf = ibuf;
239
240                 ibuf = obuf;
241                 obuf = tmp_buf;
242
243                 rte_pktmbuf_reset(ibuf);
244                 rte_pktmbuf_reset(obuf);
245
246                 rte_pktmbuf_append(ibuf, tdata->ciphertext.len);
247
248                 /* only encryption requires plaintext.data input,
249                  * decryption/(digest gen)/(digest verify) use ciphertext.data
250                  * to be computed
251                  */
252                 if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
253                         pktmbuf_write(ibuf, 0, tdata->plaintext.len,
254                                         tdata->plaintext.data);
255                 else
256                         pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
257                                         tdata->ciphertext.data);
258
259                 buf_p = rte_pktmbuf_append(ibuf, digest_len);
260                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
261                         rte_memcpy(buf_p, tdata->digest.data, digest_len);
262                 else
263                         memset(buf_p, 0, digest_len);
264
265                 memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
266
267                 buf_p = rte_pktmbuf_append(obuf, buf_len);
268                 if (!buf_p) {
269                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
270                                 "FAILED: %s", __LINE__,
271                                 "No room to append mbuf");
272                         status = TEST_FAILED;
273                         goto error_exit;
274                 }
275                 memset(buf_p, 0, buf_len);
276         }
277
278         sym_op->m_src = ibuf;
279
280         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
281                 sym_op->m_dst = obuf;
282                 iobuf = obuf;
283         } else {
284                 sym_op->m_dst = NULL;
285                 iobuf = ibuf;
286         }
287
288         /* sessionless op requires allocate xform using
289          * rte_crypto_op_sym_xforms_alloc(), otherwise rte_zmalloc()
290          * is used
291          */
292         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
293                 uint32_t n_xforms = 0;
294
295                 if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
296                         n_xforms++;
297                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
298                         n_xforms++;
299
300                 if (rte_crypto_op_sym_xforms_alloc(op, n_xforms)
301                         == NULL) {
302                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
303                                 "FAILED: %s", __LINE__, "Failed to "
304                                 "allocate space for crypto transforms");
305                         status = TEST_FAILED;
306                         goto error_exit;
307                 }
308         } else {
309                 cipher_xform = rte_zmalloc(NULL,
310                         sizeof(struct rte_crypto_sym_xform), 0);
311
312                 auth_xform = rte_zmalloc(NULL,
313                         sizeof(struct rte_crypto_sym_xform), 0);
314
315                 if (!cipher_xform || !auth_xform) {
316                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
317                                 "FAILED: %s", __LINE__, "Failed to "
318                                 "allocate memory for crypto transforms");
319                         status = TEST_FAILED;
320                         goto error_exit;
321                 }
322         }
323
324         /* preparing xform, for sessioned op, init_xform is initialized
325          * here and later as param in rte_cryptodev_sym_session_create() call
326          */
327         if (t->op_mask == BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN) {
328                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
329                         cipher_xform = op->sym->xform;
330                         auth_xform = cipher_xform->next;
331                         auth_xform->next = NULL;
332                 } else {
333                         cipher_xform->next = auth_xform;
334                         auth_xform->next = NULL;
335                         init_xform = cipher_xform;
336                 }
337         } else if (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC) {
338                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
339                         auth_xform = op->sym->xform;
340                         cipher_xform = auth_xform->next;
341                         cipher_xform->next = NULL;
342                 } else {
343                         auth_xform->next = cipher_xform;
344                         cipher_xform->next = NULL;
345                         init_xform = auth_xform;
346                 }
347         } else if ((t->op_mask == BLOCKCIPHER_TEST_OP_ENCRYPT) ||
348                         (t->op_mask == BLOCKCIPHER_TEST_OP_DECRYPT)) {
349                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
350                         cipher_xform = op->sym->xform;
351                 else
352                         init_xform = cipher_xform;
353                 cipher_xform->next = NULL;
354         } else if ((t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_GEN) ||
355                         (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY)) {
356                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
357                         auth_xform = op->sym->xform;
358                 else
359                         init_xform = auth_xform;
360                 auth_xform->next = NULL;
361         } else {
362                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
363                         "line %u FAILED: %s",
364                         __LINE__, "Unrecognized operation");
365                 status = TEST_FAILED;
366                 goto error_exit;
367         }
368
369         /*configure xforms & sym_op cipher and auth data*/
370         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
371                 cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
372                 cipher_xform->cipher.algo = tdata->crypto_algo;
373                 if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
374                         cipher_xform->cipher.op =
375                                 RTE_CRYPTO_CIPHER_OP_ENCRYPT;
376                 else
377                         cipher_xform->cipher.op =
378                                 RTE_CRYPTO_CIPHER_OP_DECRYPT;
379                 cipher_xform->cipher.key.data = cipher_key;
380                 cipher_xform->cipher.key.length = tdata->cipher_key.len;
381                 cipher_xform->cipher.iv.offset = IV_OFFSET;
382
383                 if (tdata->crypto_algo == RTE_CRYPTO_CIPHER_NULL)
384                         cipher_xform->cipher.iv.length = 0;
385                 else
386                         cipher_xform->cipher.iv.length = tdata->iv.len;
387
388                 sym_op->cipher.data.offset = tdata->cipher_offset;
389                 sym_op->cipher.data.length = tdata->ciphertext.len -
390                                 tdata->cipher_offset;
391                 rte_memcpy(rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET),
392                                 tdata->iv.data,
393                                 tdata->iv.len);
394         }
395
396         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
397                 uint32_t digest_offset = tdata->ciphertext.len;
398
399                 auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
400                 auth_xform->auth.algo = tdata->auth_algo;
401                 auth_xform->auth.key.length = tdata->auth_key.len;
402                 auth_xform->auth.key.data = auth_key;
403                 auth_xform->auth.digest_length = digest_len;
404
405                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
406                         auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
407                         sym_op->auth.digest.data = pktmbuf_mtod_offset
408                                 (iobuf, digest_offset);
409                         sym_op->auth.digest.phys_addr =
410                                 pktmbuf_iova_offset(iobuf,
411                                         digest_offset);
412                 } else {
413                         auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
414                         sym_op->auth.digest.data = pktmbuf_mtod_offset
415                                 (sym_op->m_src, digest_offset);
416                         sym_op->auth.digest.phys_addr =
417                                 pktmbuf_iova_offset(sym_op->m_src,
418                                         digest_offset);
419                 }
420
421                 sym_op->auth.data.offset = tdata->auth_offset;
422                 sym_op->auth.data.length = tdata->ciphertext.len -
423                                 tdata->auth_offset;
424         }
425
426         /**
427          * Create session for sessioned op. For mbuf iteration test,
428          * skip the session creation for the second iteration.
429          */
430         if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) &&
431                         nb_iterates == 0) {
432                 sess = rte_cryptodev_sym_session_create(sess_mpool);
433
434                 status = rte_cryptodev_sym_session_init(dev_id, sess,
435                                 init_xform, sess_priv_mpool);
436                 if (status == -ENOTSUP) {
437                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "UNSUPPORTED");
438                         status = TEST_SKIPPED;
439                         goto error_exit;
440                 }
441                 if (!sess || status < 0) {
442                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
443                                 "FAILED: %s", __LINE__,
444                                 "Session creation failed");
445                         status = TEST_FAILED;
446                         goto error_exit;
447                 }
448
449                 /* attach symmetric crypto session to crypto operations */
450                 rte_crypto_op_attach_sym_session(op, sess);
451         }
452
453         debug_hexdump(stdout, "m_src(before):",
454                         sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
455         rte_memcpy(tmp_src_buf, sym_op->m_src->buf_addr,
456                                                 sym_op->m_src->buf_len);
457         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
458                 debug_hexdump(stdout, "m_dst(before):",
459                         sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
460                 rte_memcpy(tmp_dst_buf, sym_op->m_dst->buf_addr,
461                                                 sym_op->m_dst->buf_len);
462         }
463
464         /* Process crypto operation */
465         if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
466                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
467                         "line %u FAILED: %s",
468                         __LINE__, "Error sending packet for encryption");
469                 status = TEST_FAILED;
470                 goto error_exit;
471         }
472
473         op = NULL;
474
475         while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
476                 rte_pause();
477
478         if (!op) {
479                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
480                         "line %u FAILED: %s",
481                         __LINE__, "Failed to process sym crypto op");
482                 status = TEST_FAILED;
483                 goto error_exit;
484         }
485
486         debug_hexdump(stdout, "m_src(after):",
487                         sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
488         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
489                 debug_hexdump(stdout, "m_dst(after):",
490                         sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
491
492         /* Verify results */
493         if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
494                 if ((t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY) &&
495                         (op->status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED))
496                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
497                                 "FAILED: Digest verification failed "
498                                 "(0x%X)", __LINE__, op->status);
499                 else
500                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
501                                 "FAILED: Operation failed "
502                                 "(0x%X)", __LINE__, op->status);
503                 status = TEST_FAILED;
504                 goto error_exit;
505         }
506
507         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
508                 uint8_t buffer[2048];
509                 const uint8_t *compare_ref;
510                 uint32_t compare_len;
511
512                 if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
513                         compare_ref = tdata->ciphertext.data +
514                                         tdata->cipher_offset;
515                         compare_len = tdata->ciphertext.len -
516                                         tdata->cipher_offset;
517                 } else {
518                         compare_ref = tdata->plaintext.data +
519                                         tdata->cipher_offset;
520                         compare_len = tdata->plaintext.len -
521                                         tdata->cipher_offset;
522                 }
523
524                 if (memcmp(rte_pktmbuf_read(iobuf, tdata->cipher_offset,
525                                 compare_len, buffer), compare_ref,
526                                 compare_len)) {
527                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
528                                 "FAILED: %s", __LINE__,
529                                 "Crypto data not as expected");
530                         status = TEST_FAILED;
531                         goto error_exit;
532                 }
533         }
534
535         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
536                 uint8_t *auth_res = pktmbuf_mtod_offset(iobuf,
537                                         tdata->ciphertext.len);
538
539                 if (memcmp(auth_res, tdata->digest.data, digest_len)) {
540                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
541                                 "FAILED: %s", __LINE__, "Generated "
542                                 "digest data not as expected");
543                         status = TEST_FAILED;
544                         goto error_exit;
545                 }
546         }
547
548         /* The only parts that should have changed in the buffer are
549          * plaintext/ciphertext and digest.
550          * In OOP only the dest buffer should change.
551          */
552         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
553                 struct rte_mbuf *mbuf;
554                 uint8_t value;
555                 uint32_t head_unchanged_len, changed_len = 0;
556                 uint32_t i;
557                 uint32_t hdroom_used = 0, tlroom_used = 0;
558                 uint32_t hdroom = 0;
559
560                 mbuf = sym_op->m_src;
561                 /*
562                  * Crypto PMDs specify the headroom & tailroom it would use
563                  * when processing the crypto operation. PMD is free to modify
564                  * this space, and so the verification check should skip that
565                  * block.
566                  */
567                 hdroom_used = dev_info.min_mbuf_headroom_req;
568                 tlroom_used = dev_info.min_mbuf_tailroom_req;
569
570                 /* Get headroom */
571                 hdroom = rte_pktmbuf_headroom(mbuf);
572
573                 head_unchanged_len = mbuf->buf_len;
574
575                 for (i = 0; i < mbuf->buf_len; i++) {
576
577                         /* Skip headroom used by PMD */
578                         if (i == hdroom - hdroom_used)
579                                 i += hdroom_used;
580
581                         /* Skip tailroom used by PMD */
582                         if (i == (hdroom + mbuf->data_len))
583                                 i += tlroom_used;
584
585                         value = *((uint8_t *)(mbuf->buf_addr)+i);
586                         if (value != tmp_src_buf[i]) {
587                                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
588         "line %u FAILED: OOP src outer mbuf data (0x%x) not as expected (0x%x)",
589                                         __LINE__, value, tmp_src_buf[i]);
590                                 status = TEST_FAILED;
591                                 goto error_exit;
592                         }
593                 }
594
595                 mbuf = sym_op->m_dst;
596                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
597                         head_unchanged_len = hdroom + sym_op->auth.data.offset;
598                         changed_len = sym_op->auth.data.length;
599                         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
600                                 changed_len += digest_len;
601                 } else {
602                         /* cipher-only */
603                         head_unchanged_len = hdroom +
604                                         sym_op->cipher.data.offset;
605                         changed_len = sym_op->cipher.data.length;
606                 }
607
608                 for (i = 0; i < mbuf->buf_len; i++) {
609                         if (i == head_unchanged_len)
610                                 i += changed_len;
611                         value = *((uint8_t *)(mbuf->buf_addr)+i);
612                         if (value != tmp_dst_buf[i]) {
613                                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
614                                 "line %u FAILED: OOP dst outer mbuf data "
615                                 "(0x%x) not as expected (0x%x)",
616                                 __LINE__, value, tmp_dst_buf[i]);
617                                 status = TEST_FAILED;
618                                 goto error_exit;
619                         }
620                 }
621
622                 if (!nb_iterates) {
623                         nb_iterates++;
624                         goto iterate;
625                 }
626         } else {
627                 /* In-place operation */
628                 struct rte_mbuf *mbuf;
629                 uint8_t value;
630                 uint32_t head_unchanged_len = 0, changed_len = 0;
631                 uint32_t i;
632                 uint32_t hdroom_used = 0, tlroom_used = 0;
633                 uint32_t hdroom = 0;
634
635                 /*
636                  * Crypto PMDs specify the headroom & tailroom it would use
637                  * when processing the crypto operation. PMD is free to modify
638                  * this space, and so the verification check should skip that
639                  * block.
640                  */
641                 hdroom_used = dev_info.min_mbuf_headroom_req;
642                 tlroom_used = dev_info.min_mbuf_tailroom_req;
643
644                 mbuf = sym_op->m_src;
645
646                 /* Get headroom */
647                 hdroom = rte_pktmbuf_headroom(mbuf);
648
649                 if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
650                         head_unchanged_len = hdroom +
651                                         sym_op->cipher.data.offset;
652                         changed_len = sym_op->cipher.data.length;
653                 } else {
654                         /* auth-only */
655                         head_unchanged_len = hdroom +
656                                         sym_op->auth.data.offset +
657                                         sym_op->auth.data.length;
658                         changed_len = 0;
659                 }
660
661                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
662                         changed_len += digest_len;
663
664                 for (i = 0; i < mbuf->buf_len; i++) {
665
666                         /* Skip headroom used by PMD */
667                         if (i == hdroom - hdroom_used)
668                                 i += hdroom_used;
669
670                         if (i == head_unchanged_len)
671                                 i += changed_len;
672
673                         /* Skip tailroom used by PMD */
674                         if (i == (hdroom + mbuf->data_len))
675                                 i += tlroom_used;
676
677                         value = *((uint8_t *)(mbuf->buf_addr)+i);
678                         if (value != tmp_src_buf[i]) {
679                                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
680                                 "line %u FAILED: outer mbuf data (0x%x) "
681                                 "not as expected (0x%x)",
682                                 __LINE__, value, tmp_src_buf[i]);
683                                 status = TEST_FAILED;
684                                 goto error_exit;
685                         }
686                 }
687         }
688
689         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "PASS");
690
691 error_exit:
692         if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
693                 if (sess) {
694                         rte_cryptodev_sym_session_clear(dev_id, sess);
695                         rte_cryptodev_sym_session_free(sess);
696                 }
697                 if (cipher_xform)
698                         rte_free(cipher_xform);
699                 if (auth_xform)
700                         rte_free(auth_xform);
701         }
702
703         if (op)
704                 rte_crypto_op_free(op);
705
706         if (obuf)
707                 rte_pktmbuf_free(obuf);
708
709         if (ibuf)
710                 rte_pktmbuf_free(ibuf);
711
712         return status;
713 }
714
715 int
716 test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
717         struct rte_mempool *op_mpool,
718         struct rte_mempool *sess_mpool,
719         struct rte_mempool *sess_priv_mpool,
720         uint8_t dev_id,
721         enum blockcipher_test_type test_type)
722 {
723         int status, overall_status = TEST_SUCCESS;
724         uint32_t i, test_index = 0;
725         char test_msg[BLOCKCIPHER_TEST_MSG_LEN + 1];
726         uint32_t n_test_cases = 0;
727         const struct blockcipher_test_case *tcs = NULL;
728
729         switch (test_type) {
730         case BLKCIPHER_AES_CHAIN_TYPE:
731                 n_test_cases = sizeof(aes_chain_test_cases) /
732                 sizeof(aes_chain_test_cases[0]);
733                 tcs = aes_chain_test_cases;
734                 break;
735         case BLKCIPHER_AES_CIPHERONLY_TYPE:
736                 n_test_cases = sizeof(aes_cipheronly_test_cases) /
737                 sizeof(aes_cipheronly_test_cases[0]);
738                 tcs = aes_cipheronly_test_cases;
739                 break;
740         case BLKCIPHER_AES_DOCSIS_TYPE:
741                 n_test_cases = sizeof(aes_docsis_test_cases) /
742                 sizeof(aes_docsis_test_cases[0]);
743                 tcs = aes_docsis_test_cases;
744                 break;
745         case BLKCIPHER_3DES_CHAIN_TYPE:
746                 n_test_cases = sizeof(triple_des_chain_test_cases) /
747                 sizeof(triple_des_chain_test_cases[0]);
748                 tcs = triple_des_chain_test_cases;
749                 break;
750         case BLKCIPHER_3DES_CIPHERONLY_TYPE:
751                 n_test_cases = sizeof(triple_des_cipheronly_test_cases) /
752                 sizeof(triple_des_cipheronly_test_cases[0]);
753                 tcs = triple_des_cipheronly_test_cases;
754                 break;
755         case BLKCIPHER_DES_CIPHERONLY_TYPE:
756                 n_test_cases = sizeof(des_cipheronly_test_cases) /
757                 sizeof(des_cipheronly_test_cases[0]);
758                 tcs = des_cipheronly_test_cases;
759                 break;
760         case BLKCIPHER_DES_DOCSIS_TYPE:
761                 n_test_cases = sizeof(des_docsis_test_cases) /
762                 sizeof(des_docsis_test_cases[0]);
763                 tcs = des_docsis_test_cases;
764                 break;
765         case BLKCIPHER_AUTHONLY_TYPE:
766                 n_test_cases = sizeof(hash_test_cases) /
767                 sizeof(hash_test_cases[0]);
768                 tcs = hash_test_cases;
769                 break;
770         default:
771                 break;
772         }
773
774         for (i = 0; i < n_test_cases; i++) {
775                 const struct blockcipher_test_case *tc = &tcs[i];
776
777                 status = test_blockcipher_one_case(tc, mbuf_pool, op_mpool,
778                         sess_mpool, sess_priv_mpool, dev_id,
779                         test_msg);
780
781                 printf("  %u) TestCase %s %s\n", test_index ++,
782                         tc->test_descr, test_msg);
783
784                 if (status == TEST_FAILED) {
785                         overall_status = status;
786
787                         if (tc->feature_mask & BLOCKCIPHER_TEST_FEATURE_STOPPER)
788                                 break;
789                 }
790         }
791
792         return overall_status;
793 }