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_SUCCESS; 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 } 895