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 } 539