Imported Upstream version 16.11
[deb_dpdk.git] / app / test / test_cryptodev_blockcipher.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *       * Redistributions of source code must retain the above copyright
11  *         notice, this list of conditions and the following disclaimer.
12  *       * Redistributions in binary form must reproduce the above copyright
13  *         notice, this list of conditions and the following disclaimer in
14  *         the documentation and/or other materials provided with the
15  *         distribution.
16  *       * Neither the name of Intel Corporation nor the names of its
17  *         contributors may be used to endorse or promote products derived
18  *         from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <rte_common.h>
34 #include <rte_hexdump.h>
35 #include <rte_mbuf.h>
36 #include <rte_malloc.h>
37 #include <rte_memcpy.h>
38
39 #include <rte_crypto.h>
40 #include <rte_cryptodev.h>
41 #include <rte_cryptodev_pmd.h>
42
43 #include "test.h"
44 #include "test_cryptodev_blockcipher.h"
45 #include "test_cryptodev_aes_test_vectors.h"
46 #include "test_cryptodev_des_test_vectors.h"
47 #include "test_cryptodev_hash_test_vectors.h"
48
49 static int
50 test_blockcipher_one_case(const struct blockcipher_test_case *t,
51         struct rte_mempool *mbuf_pool,
52         struct rte_mempool *op_mpool,
53         uint8_t dev_id,
54         enum rte_cryptodev_type cryptodev_type,
55         char *test_msg)
56 {
57         struct rte_mbuf *ibuf = NULL;
58         struct rte_mbuf *obuf = NULL;
59         struct rte_mbuf *iobuf;
60         struct rte_crypto_sym_xform *cipher_xform = NULL;
61         struct rte_crypto_sym_xform *auth_xform = NULL;
62         struct rte_crypto_sym_xform *init_xform = NULL;
63         struct rte_crypto_sym_op *sym_op = NULL;
64         struct rte_crypto_op *op = NULL;
65         struct rte_cryptodev_sym_session *sess = NULL;
66
67         int status = TEST_SUCCESS;
68         const struct blockcipher_test_data *tdata = t->test_data;
69         uint8_t cipher_key[tdata->cipher_key.len];
70         uint8_t auth_key[tdata->auth_key.len];
71         uint32_t buf_len = tdata->ciphertext.len;
72         uint32_t digest_len = 0;
73         char *buf_p = NULL;
74
75         if (tdata->cipher_key.len)
76                 memcpy(cipher_key, tdata->cipher_key.data,
77                         tdata->cipher_key.len);
78         if (tdata->auth_key.len)
79                 memcpy(auth_key, tdata->auth_key.data,
80                         tdata->auth_key.len);
81
82         switch (cryptodev_type) {
83         case RTE_CRYPTODEV_QAT_SYM_PMD:
84         case RTE_CRYPTODEV_OPENSSL_PMD:
85                 digest_len = tdata->digest.len;
86                 break;
87         case RTE_CRYPTODEV_AESNI_MB_PMD:
88                 digest_len = tdata->digest.truncated_len;
89                 break;
90         default:
91                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
92                         "line %u FAILED: %s",
93                         __LINE__, "Unsupported PMD type");
94                 status = TEST_FAILED;
95                 goto error_exit;
96         }
97
98         /* preparing data */
99         ibuf = rte_pktmbuf_alloc(mbuf_pool);
100         if (!ibuf) {
101                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
102                         "line %u FAILED: %s",
103                         __LINE__, "Allocation of rte_mbuf failed");
104                 status = TEST_FAILED;
105                 goto error_exit;
106         }
107
108         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
109                 buf_len += tdata->iv.len;
110         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
111                 buf_len += digest_len;
112
113         buf_p = rte_pktmbuf_append(ibuf, buf_len);
114         if (!buf_p) {
115                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
116                         "line %u FAILED: %s",
117                         __LINE__, "No room to append mbuf");
118                 status = TEST_FAILED;
119                 goto error_exit;
120         }
121
122         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
123                 rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
124                 buf_p += tdata->iv.len;
125         }
126
127         /* only encryption requires plaintext.data input,
128          * decryption/(digest gen)/(digest verify) use ciphertext.data
129          * to be computed
130          */
131         if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
132                 rte_memcpy(buf_p, tdata->plaintext.data,
133                         tdata->plaintext.len);
134                 buf_p += tdata->plaintext.len;
135         } else {
136                 rte_memcpy(buf_p, tdata->ciphertext.data,
137                         tdata->ciphertext.len);
138                 buf_p += tdata->ciphertext.len;
139         }
140
141         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
142                 rte_memcpy(buf_p, tdata->digest.data, digest_len);
143         else
144                 memset(buf_p, 0, digest_len);
145
146         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
147                 obuf = rte_pktmbuf_alloc(mbuf_pool);
148                 if (!obuf) {
149                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
150                                 "FAILED: %s", __LINE__,
151                                 "Allocation of rte_mbuf failed");
152                         status = TEST_FAILED;
153                         goto error_exit;
154                 }
155
156                 buf_p = rte_pktmbuf_append(obuf, buf_len);
157                 if (!buf_p) {
158                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
159                                 "FAILED: %s", __LINE__,
160                                 "No room to append mbuf");
161                         status = TEST_FAILED;
162                         goto error_exit;
163                 }
164                 memset(buf_p, 0, buf_len);
165         }
166
167         /* Generate Crypto op data structure */
168         op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
169         if (!op) {
170                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
171                         "line %u FAILED: %s",
172                         __LINE__, "Failed to allocate symmetric crypto "
173                         "operation struct");
174                 status = TEST_FAILED;
175                 goto error_exit;
176         }
177
178         sym_op = op->sym;
179
180         sym_op->m_src = ibuf;
181
182         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
183                 sym_op->m_dst = obuf;
184                 iobuf = obuf;
185         } else {
186                 sym_op->m_dst = NULL;
187                 iobuf = ibuf;
188         }
189
190         /* sessionless op requires allocate xform using
191          * rte_crypto_op_sym_xforms_alloc(), otherwise rte_zmalloc()
192          * is used
193          */
194         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
195                 uint32_t n_xforms = 0;
196
197                 if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
198                         n_xforms++;
199                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
200                         n_xforms++;
201
202                 if (rte_crypto_op_sym_xforms_alloc(op, n_xforms)
203                         == NULL) {
204                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
205                                 "FAILED: %s", __LINE__, "Failed to "
206                                 "allocate space for crypto transforms");
207                         status = TEST_FAILED;
208                         goto error_exit;
209                 }
210         } else {
211                 cipher_xform = rte_zmalloc(NULL,
212                         sizeof(struct rte_crypto_sym_xform), 0);
213
214                 auth_xform = rte_zmalloc(NULL,
215                         sizeof(struct rte_crypto_sym_xform), 0);
216
217                 if (!cipher_xform || !auth_xform) {
218                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
219                                 "FAILED: %s", __LINE__, "Failed to "
220                                 "allocate memory for crypto transforms");
221                         status = TEST_FAILED;
222                         goto error_exit;
223                 }
224         }
225
226         /* preparing xform, for sessioned op, init_xform is initialized
227          * here and later as param in rte_cryptodev_sym_session_create() call
228          */
229         if (t->op_mask == BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN) {
230                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
231                         cipher_xform = op->sym->xform;
232                         auth_xform = cipher_xform->next;
233                         auth_xform->next = NULL;
234                 } else {
235                         cipher_xform->next = auth_xform;
236                         auth_xform->next = NULL;
237                         init_xform = cipher_xform;
238                 }
239         } else if (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC) {
240                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
241                         auth_xform = op->sym->xform;
242                         cipher_xform = auth_xform->next;
243                         cipher_xform->next = NULL;
244                 } else {
245                         auth_xform->next = cipher_xform;
246                         cipher_xform->next = NULL;
247                         init_xform = auth_xform;
248                 }
249         } else if ((t->op_mask == BLOCKCIPHER_TEST_OP_ENCRYPT) ||
250                         (t->op_mask == BLOCKCIPHER_TEST_OP_DECRYPT)) {
251                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
252                         cipher_xform = op->sym->xform;
253                 else
254                         init_xform = cipher_xform;
255                 cipher_xform->next = NULL;
256         } else if ((t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_GEN) ||
257                         (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY)) {
258                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
259                         auth_xform = op->sym->xform;
260                 else
261                         init_xform = auth_xform;
262                 auth_xform->next = NULL;
263         } else {
264                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
265                         "line %u FAILED: %s",
266                         __LINE__, "Unrecognized operation");
267                 status = TEST_FAILED;
268                 goto error_exit;
269         }
270
271         /*configure xforms & sym_op cipher and auth data*/
272         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
273                 cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
274                 cipher_xform->cipher.algo = tdata->crypto_algo;
275                 if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
276                         cipher_xform->cipher.op =
277                                 RTE_CRYPTO_CIPHER_OP_ENCRYPT;
278                 else
279                         cipher_xform->cipher.op =
280                                 RTE_CRYPTO_CIPHER_OP_DECRYPT;
281                 cipher_xform->cipher.key.data = cipher_key;
282                 cipher_xform->cipher.key.length = tdata->cipher_key.len;
283
284                 sym_op->cipher.data.offset = tdata->iv.len;
285                 sym_op->cipher.data.length = tdata->ciphertext.len;
286                 sym_op->cipher.iv.data = rte_pktmbuf_mtod(sym_op->m_src,
287                         uint8_t *);
288                 sym_op->cipher.iv.length = tdata->iv.len;
289                 sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(
290                         sym_op->m_src);
291         }
292
293         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
294                 uint32_t auth_data_offset = 0;
295                 uint32_t digest_offset = tdata->ciphertext.len;
296
297                 if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
298                         digest_offset += tdata->iv.len;
299                         auth_data_offset += tdata->iv.len;
300                 }
301
302                 auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
303                 auth_xform->auth.algo = tdata->auth_algo;
304                 auth_xform->auth.key.length = tdata->auth_key.len;
305                 auth_xform->auth.key.data = auth_key;
306                 auth_xform->auth.digest_length = digest_len;
307
308                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
309                         auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
310                         sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
311                                 (iobuf, uint8_t *, digest_offset);
312                         sym_op->auth.digest.phys_addr =
313                                 rte_pktmbuf_mtophys_offset(iobuf,
314                                         digest_offset);
315                 } else {
316                         auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
317                         sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
318                                 (sym_op->m_src, uint8_t *, digest_offset);
319                         sym_op->auth.digest.phys_addr =
320                                 rte_pktmbuf_mtophys_offset(sym_op->m_src,
321                                         digest_offset);
322                 }
323
324                 sym_op->auth.data.offset = auth_data_offset;
325                 sym_op->auth.data.length = tdata->ciphertext.len;
326                 sym_op->auth.digest.length = digest_len;
327         }
328
329         /* create session for sessioned op */
330         if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
331                 sess = rte_cryptodev_sym_session_create(dev_id,
332                         init_xform);
333                 if (!sess) {
334                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
335                                 "FAILED: %s", __LINE__,
336                                 "Session creation failed");
337                         status = TEST_FAILED;
338                         goto error_exit;
339                 }
340
341                 /* attach symmetric crypto session to crypto operations */
342                 rte_crypto_op_attach_sym_session(op, sess);
343         }
344
345         /* Process crypto operation */
346         if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
347                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
348                         "line %u FAILED: %s",
349                         __LINE__, "Error sending packet for encryption");
350                 status = TEST_FAILED;
351                 goto error_exit;
352         }
353
354         op = NULL;
355
356         while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
357                 rte_pause();
358
359         if (!op) {
360                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
361                         "line %u FAILED: %s",
362                         __LINE__, "Failed to process sym crypto op");
363                 status = TEST_FAILED;
364                 goto error_exit;
365         }
366
367         TEST_HEXDUMP(stdout, "m_src:",
368                 rte_pktmbuf_mtod(sym_op->m_src, uint8_t *), buf_len);
369         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
370                 TEST_HEXDUMP(stdout, "m_dst:",
371                         rte_pktmbuf_mtod(sym_op->m_dst, uint8_t *),
372                         buf_len);
373
374         /* Verify results */
375         if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
376                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
377                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
378                                 "FAILED: Digest verification failed "
379                                 "(0x%X)", __LINE__, op->status);
380                 else
381                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
382                                 "FAILED: Digest verification failed "
383                                 "(0x%X)", __LINE__, op->status);
384                 status = TEST_FAILED;
385                 goto error_exit;
386         }
387
388         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
389                 uint8_t *crypto_res;
390                 const uint8_t *compare_ref;
391                 uint32_t compare_len;
392
393                 crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
394                         tdata->iv.len);
395
396                 if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
397                         compare_ref = tdata->ciphertext.data;
398                         compare_len = tdata->ciphertext.len;
399                 } else {
400                         compare_ref = tdata->plaintext.data;
401                         compare_len = tdata->plaintext.len;
402                 }
403
404                 if (memcmp(crypto_res, compare_ref, compare_len)) {
405                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
406                                 "FAILED: %s", __LINE__,
407                                 "Crypto data not as expected");
408                         status = TEST_FAILED;
409                         goto error_exit;
410                 }
411         }
412
413         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
414                 uint8_t *auth_res;
415
416                 if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
417                         auth_res = rte_pktmbuf_mtod_offset(iobuf,
418                                 uint8_t *,
419                                 tdata->iv.len + tdata->ciphertext.len);
420                 else
421                         auth_res = rte_pktmbuf_mtod_offset(iobuf,
422                                 uint8_t *, tdata->ciphertext.len);
423
424                 if (memcmp(auth_res, tdata->digest.data, digest_len)) {
425                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
426                                 "FAILED: %s", __LINE__, "Generated "
427                                 "digest data not as expected");
428                         status = TEST_FAILED;
429                         goto error_exit;
430                 }
431         }
432
433         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "PASS");
434
435 error_exit:
436         if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
437                 if (sess)
438                         rte_cryptodev_sym_session_free(dev_id, sess);
439                 if (cipher_xform)
440                         rte_free(cipher_xform);
441                 if (auth_xform)
442                         rte_free(auth_xform);
443         }
444
445         if (op)
446                 rte_crypto_op_free(op);
447
448         if (obuf)
449                 rte_pktmbuf_free(obuf);
450
451         if (ibuf)
452                 rte_pktmbuf_free(ibuf);
453
454         return status;
455 }
456
457 int
458 test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
459         struct rte_mempool *op_mpool,
460         uint8_t dev_id,
461         enum rte_cryptodev_type cryptodev_type,
462         enum blockcipher_test_type test_type)
463 {
464         int status, overall_status = TEST_SUCCESS;
465         uint32_t i, test_index = 0;
466         char test_msg[BLOCKCIPHER_TEST_MSG_LEN + 1];
467         uint32_t n_test_cases = 0;
468         uint32_t target_pmd_mask = 0;
469         const struct blockcipher_test_case *tcs = NULL;
470
471         switch (test_type) {
472         case BLKCIPHER_AES_CHAIN_TYPE:
473                 n_test_cases = sizeof(aes_chain_test_cases) /
474                 sizeof(aes_chain_test_cases[0]);
475                 tcs = aes_chain_test_cases;
476                 break;
477         case BLKCIPHER_AES_CIPHERONLY_TYPE:
478                 n_test_cases = sizeof(aes_cipheronly_test_cases) /
479                 sizeof(aes_cipheronly_test_cases[0]);
480                 tcs = aes_cipheronly_test_cases;
481                 break;
482         case BLKCIPHER_3DES_CHAIN_TYPE:
483                 n_test_cases = sizeof(triple_des_chain_test_cases) /
484                 sizeof(triple_des_chain_test_cases[0]);
485                 tcs = triple_des_chain_test_cases;
486                 break;
487         case BLKCIPHER_3DES_CIPHERONLY_TYPE:
488                 n_test_cases = sizeof(triple_des_cipheronly_test_cases) /
489                 sizeof(triple_des_cipheronly_test_cases[0]);
490                 tcs = triple_des_cipheronly_test_cases;
491                 break;
492         case BLKCIPHER_AUTHONLY_TYPE:
493                 n_test_cases = sizeof(hash_test_cases) /
494                 sizeof(hash_test_cases[0]);
495                 tcs = hash_test_cases;
496                 break;
497         default:
498                 break;
499         }
500
501         switch (cryptodev_type) {
502         case RTE_CRYPTODEV_AESNI_MB_PMD:
503                 target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB;
504                 break;
505         case RTE_CRYPTODEV_QAT_SYM_PMD:
506                 target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_QAT;
507                 break;
508         case RTE_CRYPTODEV_OPENSSL_PMD:
509                 target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL;
510                 break;
511         default:
512                 TEST_ASSERT(0, "Unrecognized cryptodev type");
513                 break;
514         }
515
516         for (i = 0; i < n_test_cases; i++) {
517                 const struct blockcipher_test_case *tc = &tcs[i];
518
519                 if (!(tc->pmd_mask & target_pmd_mask))
520                         continue;
521
522                 status = test_blockcipher_one_case(tc, mbuf_pool, op_mpool,
523                         dev_id, cryptodev_type, test_msg);
524
525                 printf("  %u) TestCase %s %s\n", test_index ++,
526                         tc->test_descr, test_msg);
527
528                 if (status != TEST_SUCCESS) {
529                         if (overall_status == TEST_SUCCESS)
530                                 overall_status = status;
531
532                         if (tc->feature_mask & BLOCKCIPHER_TEST_FEATURE_STOPPER)
533                                 break;
534                 }
535         }
536
537         return overall_status;
538 }