app/test: rework AES
[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
47 static int
48 test_blockcipher_one_case(const struct blockcipher_test_case *t,
49         struct rte_mempool *mbuf_pool,
50         struct rte_mempool *op_mpool,
51         uint8_t dev_id,
52         enum rte_cryptodev_type cryptodev_type,
53         char *test_msg)
54 {
55         struct rte_mbuf *ibuf = NULL;
56         struct rte_mbuf *obuf = NULL;
57         struct rte_mbuf *iobuf;
58         struct rte_crypto_sym_xform *cipher_xform = NULL;
59         struct rte_crypto_sym_xform *auth_xform = NULL;
60         struct rte_crypto_sym_xform *init_xform = NULL;
61         struct rte_crypto_sym_op *sym_op = NULL;
62         struct rte_crypto_op *op = NULL;
63         struct rte_cryptodev_sym_session *sess = NULL;
64
65         int status = TEST_SUCCESS;
66         const struct blockcipher_test_data *tdata = t->test_data;
67         uint8_t cipher_key[tdata->cipher_key.len];
68         uint8_t auth_key[tdata->auth_key.len];
69         uint32_t buf_len = tdata->ciphertext.len;
70         uint32_t digest_len = 0;
71         char *buf_p = NULL;
72
73         if (tdata->cipher_key.len)
74                 memcpy(cipher_key, tdata->cipher_key.data,
75                         tdata->cipher_key.len);
76         if (tdata->auth_key.len)
77                 memcpy(auth_key, tdata->auth_key.data,
78                         tdata->auth_key.len);
79
80         switch (cryptodev_type) {
81         case RTE_CRYPTODEV_QAT_SYM_PMD:
82                 digest_len = tdata->digest.len;
83                 break;
84         case RTE_CRYPTODEV_AESNI_MB_PMD:
85                 digest_len = tdata->digest.truncated_len;
86                 break;
87         default:
88                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
89                         "line %u FAILED: %s",
90                         __LINE__, "Unsupported PMD type");
91                 status = TEST_FAILED;
92                 goto error_exit;
93         }
94
95         /* preparing data */
96         ibuf = rte_pktmbuf_alloc(mbuf_pool);
97         if (!ibuf) {
98                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
99                         "line %u FAILED: %s",
100                         __LINE__, "Allocation of rte_mbuf failed");
101                 status = TEST_FAILED;
102                 goto error_exit;
103         }
104
105         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
106                 buf_len += tdata->iv.len;
107         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
108                 buf_len += digest_len;
109
110         buf_p = rte_pktmbuf_append(ibuf, buf_len);
111         if (!buf_p) {
112                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
113                         "line %u FAILED: %s",
114                         __LINE__, "No room to append mbuf");
115                 status = TEST_FAILED;
116                 goto error_exit;
117         }
118
119         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
120                 rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
121                 buf_p += tdata->iv.len;
122         }
123
124         /* only encryption requires plaintext.data input,
125          * decryption/(digest gen)/(digest verify) use ciphertext.data
126          * to be computed
127          */
128         if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
129                 rte_memcpy(buf_p, tdata->plaintext.data,
130                         tdata->plaintext.len);
131                 buf_p += tdata->plaintext.len;
132         } else {
133                 rte_memcpy(buf_p, tdata->ciphertext.data,
134                         tdata->ciphertext.len);
135                 buf_p += tdata->ciphertext.len;
136         }
137
138         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
139                 rte_memcpy(buf_p, tdata->digest.data, digest_len);
140         else
141                 memset(buf_p, 0, digest_len);
142
143         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
144                 obuf = rte_pktmbuf_alloc(mbuf_pool);
145                 if (!obuf) {
146                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
147                                 "FAILED: %s", __LINE__,
148                                 "Allocation of rte_mbuf failed");
149                         status = TEST_FAILED;
150                         goto error_exit;
151                 }
152
153                 buf_p = rte_pktmbuf_append(obuf, buf_len);
154                 if (!buf_p) {
155                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
156                                 "FAILED: %s", __LINE__,
157                                 "No room to append mbuf");
158                         status = TEST_FAILED;
159                         goto error_exit;
160                 }
161                 memset(buf_p, 0, buf_len);
162         }
163
164         /* Generate Crypto op data structure */
165         op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
166         if (!op) {
167                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
168                         "line %u FAILED: %s",
169                         __LINE__, "Failed to allocate symmetric crypto "
170                         "operation struct");
171                 status = TEST_FAILED;
172                 goto error_exit;
173         }
174
175         sym_op = op->sym;
176
177         sym_op->m_src = ibuf;
178
179         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
180                 sym_op->m_dst = obuf;
181                 iobuf = obuf;
182         } else {
183                 sym_op->m_dst = NULL;
184                 iobuf = ibuf;
185         }
186
187         /* sessionless op requires allocate xform using
188          * rte_crypto_op_sym_xforms_alloc(), otherwise rte_zmalloc()
189          * is used
190          */
191         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
192                 uint32_t n_xforms = 0;
193
194                 if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
195                         n_xforms++;
196                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
197                         n_xforms++;
198
199                 if (rte_crypto_op_sym_xforms_alloc(op, n_xforms)
200                         == NULL) {
201                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
202                                 "FAILED: %s", __LINE__, "Failed to "
203                                 "allocate space for crypto transforms");
204                         status = TEST_FAILED;
205                         goto error_exit;
206                 }
207         } else {
208                 cipher_xform = rte_zmalloc(NULL,
209                         sizeof(struct rte_crypto_sym_xform), 0);
210
211                 auth_xform = rte_zmalloc(NULL,
212                         sizeof(struct rte_crypto_sym_xform), 0);
213
214                 if (!cipher_xform || !auth_xform) {
215                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
216                                 "FAILED: %s", __LINE__, "Failed to "
217                                 "allocate memory for crypto transforms");
218                         status = TEST_FAILED;
219                         goto error_exit;
220                 }
221         }
222
223         /* preparing xform, for sessioned op, init_xform is initialized
224          * here and later as param in rte_cryptodev_sym_session_create() call
225          */
226         if (t->op_mask == BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN) {
227                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
228                         cipher_xform = op->sym->xform;
229                         auth_xform = cipher_xform->next;
230                         auth_xform->next = NULL;
231                 } else {
232                         cipher_xform->next = auth_xform;
233                         auth_xform->next = NULL;
234                         init_xform = cipher_xform;
235                 }
236         } else if (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC) {
237                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
238                         auth_xform = op->sym->xform;
239                         cipher_xform = auth_xform->next;
240                         cipher_xform->next = NULL;
241                 } else {
242                         auth_xform->next = cipher_xform;
243                         cipher_xform->next = NULL;
244                         init_xform = auth_xform;
245                 }
246         } else if ((t->op_mask == BLOCKCIPHER_TEST_OP_ENCRYPT) ||
247                         (t->op_mask == BLOCKCIPHER_TEST_OP_DECRYPT)) {
248                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
249                         cipher_xform = op->sym->xform;
250                 else
251                         init_xform = cipher_xform;
252                 cipher_xform->next = NULL;
253         } else if ((t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_GEN) ||
254                         (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY)) {
255                 if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
256                         auth_xform = op->sym->xform;
257                 else
258                         init_xform = auth_xform;
259                 auth_xform->next = NULL;
260         } else {
261                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
262                         "line %u FAILED: %s",
263                         __LINE__, "Unrecognized operation");
264                 status = TEST_FAILED;
265                 goto error_exit;
266         }
267
268         /*configure xforms & sym_op cipher and auth data*/
269         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
270                 cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
271                 cipher_xform->cipher.algo = tdata->crypto_algo;
272                 if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
273                         cipher_xform->cipher.op =
274                                 RTE_CRYPTO_CIPHER_OP_ENCRYPT;
275                 else
276                         cipher_xform->cipher.op =
277                                 RTE_CRYPTO_CIPHER_OP_DECRYPT;
278                 cipher_xform->cipher.key.data = cipher_key;
279                 cipher_xform->cipher.key.length = tdata->cipher_key.len;
280
281                 sym_op->cipher.data.offset = tdata->iv.len;
282                 sym_op->cipher.data.length = tdata->ciphertext.len;
283                 sym_op->cipher.iv.data = rte_pktmbuf_mtod(sym_op->m_src,
284                         uint8_t *);
285                 sym_op->cipher.iv.length = tdata->iv.len;
286                 sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(
287                         sym_op->m_src);
288         }
289
290         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
291                 uint32_t auth_data_offset = 0;
292                 uint32_t digest_offset = tdata->ciphertext.len;
293
294                 if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
295                         digest_offset += tdata->iv.len;
296                         auth_data_offset += tdata->iv.len;
297                 }
298
299                 auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
300                 auth_xform->auth.algo = tdata->auth_algo;
301                 auth_xform->auth.key.length = tdata->auth_key.len;
302                 auth_xform->auth.key.data = auth_key;
303                 auth_xform->auth.digest_length = digest_len;
304
305                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
306                         auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
307                         sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
308                                 (iobuf, uint8_t *, digest_offset);
309                         sym_op->auth.digest.phys_addr =
310                                 rte_pktmbuf_mtophys_offset(iobuf,
311                                         digest_offset);
312                 } else {
313                         auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
314                         sym_op->auth.digest.data = rte_pktmbuf_mtod_offset
315                                 (sym_op->m_src, uint8_t *, digest_offset);
316                         sym_op->auth.digest.phys_addr =
317                                 rte_pktmbuf_mtophys_offset(sym_op->m_src,
318                                         digest_offset);
319                 }
320
321                 sym_op->auth.data.offset = auth_data_offset;
322                 sym_op->auth.data.length = tdata->ciphertext.len;
323                 sym_op->auth.digest.length = digest_len;
324         }
325
326         /* create session for sessioned op */
327         if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
328                 sess = rte_cryptodev_sym_session_create(dev_id,
329                         init_xform);
330                 if (!sess) {
331                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
332                                 "FAILED: %s", __LINE__,
333                                 "Session creation failed");
334                         status = TEST_FAILED;
335                         goto error_exit;
336                 }
337
338                 /* attach symmetric crypto session to crypto operations */
339                 rte_crypto_op_attach_sym_session(op, sess);
340         }
341
342         /* Process crypto operation */
343         if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
344                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
345                         "line %u FAILED: %s",
346                         __LINE__, "Error sending packet for encryption");
347                 status = TEST_FAILED;
348                 goto error_exit;
349         }
350
351         op = NULL;
352
353         while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
354                 rte_pause();
355
356         if (!op) {
357                 snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
358                         "line %u FAILED: %s",
359                         __LINE__, "Failed to process sym crypto op");
360                 status = TEST_FAILED;
361                 goto error_exit;
362         }
363
364         TEST_HEXDUMP(stdout, "m_src:",
365                 rte_pktmbuf_mtod(sym_op->m_src, uint8_t *), buf_len);
366         if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
367                 TEST_HEXDUMP(stdout, "m_dst:",
368                         rte_pktmbuf_mtod(sym_op->m_dst, uint8_t *),
369                         buf_len);
370
371         /* Verify results */
372         if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
373                 if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
374                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
375                                 "FAILED: Digest verification failed "
376                                 "(0x%X)", __LINE__, op->status);
377                 else
378                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
379                                 "FAILED: Digest verification failed "
380                                 "(0x%X)", __LINE__, op->status);
381                 status = TEST_FAILED;
382                 goto error_exit;
383         }
384
385         if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
386                 uint8_t *crypto_res;
387                 const uint8_t *compare_ref;
388                 uint32_t compare_len;
389
390                 crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
391                         tdata->iv.len);
392
393                 if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
394                         compare_ref = tdata->ciphertext.data;
395                         compare_len = tdata->ciphertext.len;
396                 } else {
397                         compare_ref = tdata->plaintext.data;
398                         compare_len = tdata->plaintext.len;
399                 }
400
401                 if (memcmp(crypto_res, compare_ref, compare_len)) {
402                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
403                                 "FAILED: %s", __LINE__,
404                                 "Crypto data not as expected");
405                         status = TEST_FAILED;
406                         goto error_exit;
407                 }
408         }
409
410         if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
411                 uint8_t *auth_res;
412
413                 if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
414                         auth_res = rte_pktmbuf_mtod_offset(iobuf,
415                                 uint8_t *,
416                                 tdata->iv.len + tdata->ciphertext.len);
417                 else
418                         auth_res = rte_pktmbuf_mtod_offset(iobuf,
419                                 uint8_t *, tdata->ciphertext.len);
420
421                 if (memcmp(auth_res, tdata->digest.data, digest_len)) {
422                         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
423                                 "FAILED: %s", __LINE__, "Generated "
424                                 "digest data not as expected");
425                         status = TEST_FAILED;
426                         goto error_exit;
427                 }
428         }
429
430         snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "PASS");
431
432 error_exit:
433         if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
434                 if (sess)
435                         rte_cryptodev_sym_session_free(dev_id, sess);
436                 if (cipher_xform)
437                         rte_free(cipher_xform);
438                 if (auth_xform)
439                         rte_free(auth_xform);
440         }
441
442         if (op)
443                 rte_crypto_op_free(op);
444
445         if (obuf)
446                 rte_pktmbuf_free(obuf);
447
448         if (ibuf)
449                 rte_pktmbuf_free(ibuf);
450
451         return status;
452 }
453
454 int
455 test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
456         struct rte_mempool *op_mpool,
457         uint8_t dev_id,
458         enum rte_cryptodev_type cryptodev_type,
459         enum blockcipher_test_type test_type)
460 {
461         int status, overall_status = TEST_SUCCESS;
462         uint32_t i, test_index = 0;
463         char test_msg[BLOCKCIPHER_TEST_MSG_LEN + 1];
464         uint32_t n_test_cases = 0;
465         uint32_t target_pmd_mask = 0;
466         const struct blockcipher_test_case *tcs = NULL;
467
468         switch (test_type) {
469         case BLKCIPHER_AES_CHAIN_TYPE:
470                 n_test_cases = sizeof(aes_chain_test_cases) /
471                 sizeof(aes_chain_test_cases[0]);
472                 tcs = aes_chain_test_cases;
473                 break;
474         case BLKCIPHER_AES_CIPHERONLY_TYPE:
475         case BLKCIPHER_3DES_CHAIN_TYPE:
476         case BLKCIPHER_3DES_CIPHERONLY_TYPE:
477         case BLKCIPHER_AUTHONLY_TYPE:
478         default:
479                 break;
480         }
481
482         switch (cryptodev_type) {
483         case RTE_CRYPTODEV_AESNI_MB_PMD:
484                 target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB;
485                 break;
486         case RTE_CRYPTODEV_QAT_SYM_PMD:
487                 target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_QAT;
488                 break;
489         default:
490                 TEST_ASSERT(0, "Unrecognized cryptodev type");
491                 break;
492         }
493
494         for (i = 0; i < n_test_cases; i++) {
495                 const struct blockcipher_test_case *tc = &tcs[i];
496
497                 if (!(tc->pmd_mask & target_pmd_mask))
498                         continue;
499
500                 status = test_blockcipher_one_case(tc, mbuf_pool, op_mpool,
501                         dev_id, cryptodev_type, test_msg);
502
503                 printf("  %u) TestCase %s %s\n", test_index ++,
504                         tc->test_descr, test_msg);
505
506                 if (status != TEST_SUCCESS) {
507                         if (overall_status == TEST_SUCCESS)
508                                 overall_status = status;
509
510                         if (tc->feature_mask & BLOCKCIPHER_TEST_FEATURE_STOPPER)
511                                 break;
512                 }
513         }
514
515         return overall_status;
516 }