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