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