1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2021 Marvell. 3 */ 4 5 #include <rte_common.h> 6 #include <rte_cryptodev.h> 7 #include <rte_esp.h> 8 #include <rte_ip.h> 9 #include <rte_security.h> 10 #include <rte_tcp.h> 11 #include <rte_udp.h> 12 13 #include "test.h" 14 #include "test_cryptodev_security_ipsec.h" 15 16 #define IV_LEN_MAX 16 17 18 struct crypto_param_comb alg_list[RTE_DIM(aead_list) + 19 (RTE_DIM(cipher_list) * 20 RTE_DIM(auth_list))]; 21 22 static bool 23 is_valid_ipv4_pkt(const struct rte_ipv4_hdr *pkt) 24 { 25 /* The IP version number must be 4 */ 26 if (((pkt->version_ihl) >> 4) != 4) 27 return false; 28 /* 29 * The IP header length field must be large enough to hold the 30 * minimum length legal IP datagram (20 bytes = 5 words). 31 */ 32 if ((pkt->version_ihl & 0xf) < 5) 33 return false; 34 35 /* 36 * The IP total length field must be large enough to hold the IP 37 * datagram header, whose length is specified in the IP header length 38 * field. 39 */ 40 if (rte_cpu_to_be_16(pkt->total_length) < sizeof(struct rte_ipv4_hdr)) 41 return false; 42 43 return true; 44 } 45 46 static bool 47 is_valid_ipv6_pkt(const struct rte_ipv6_hdr *pkt) 48 { 49 /* The IP version number must be 6 */ 50 if ((rte_be_to_cpu_32((pkt->vtc_flow)) >> 28) != 6) 51 return false; 52 53 return true; 54 } 55 56 void 57 test_ipsec_alg_list_populate(void) 58 { 59 unsigned long i, j, index = 0; 60 61 for (i = 0; i < RTE_DIM(aead_list); i++) { 62 alg_list[index].param1 = &aead_list[i]; 63 alg_list[index].param2 = NULL; 64 index++; 65 } 66 67 for (i = 0; i < RTE_DIM(cipher_list); i++) { 68 for (j = 0; j < RTE_DIM(auth_list); j++) { 69 alg_list[index].param1 = &cipher_list[i]; 70 alg_list[index].param2 = &auth_list[j]; 71 index++; 72 } 73 } 74 } 75 76 int 77 test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform, 78 const struct rte_security_capability *sec_cap, 79 bool silent) 80 { 81 /* Verify security capabilities */ 82 83 if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) { 84 if (!silent) 85 RTE_LOG(INFO, USER1, "ESN is not supported\n"); 86 return -ENOTSUP; 87 } 88 89 if (ipsec_xform->options.udp_encap == 1 && 90 sec_cap->ipsec.options.udp_encap == 0) { 91 if (!silent) 92 RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n"); 93 return -ENOTSUP; 94 } 95 96 if (ipsec_xform->options.udp_ports_verify == 1 && 97 sec_cap->ipsec.options.udp_ports_verify == 0) { 98 if (!silent) 99 RTE_LOG(INFO, USER1, "UDP encapsulation ports " 100 "verification is not supported\n"); 101 return -ENOTSUP; 102 } 103 104 if (ipsec_xform->options.copy_dscp == 1 && 105 sec_cap->ipsec.options.copy_dscp == 0) { 106 if (!silent) 107 RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n"); 108 return -ENOTSUP; 109 } 110 111 if (ipsec_xform->options.copy_flabel == 1 && 112 sec_cap->ipsec.options.copy_flabel == 0) { 113 if (!silent) 114 RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n"); 115 return -ENOTSUP; 116 } 117 118 if (ipsec_xform->options.copy_df == 1 && 119 sec_cap->ipsec.options.copy_df == 0) { 120 if (!silent) 121 RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n"); 122 return -ENOTSUP; 123 } 124 125 if (ipsec_xform->options.dec_ttl == 1 && 126 sec_cap->ipsec.options.dec_ttl == 0) { 127 if (!silent) 128 RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n"); 129 return -ENOTSUP; 130 } 131 132 if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) { 133 if (!silent) 134 RTE_LOG(INFO, USER1, "ECN is not supported\n"); 135 return -ENOTSUP; 136 } 137 138 if (ipsec_xform->options.stats == 1 && 139 sec_cap->ipsec.options.stats == 0) { 140 if (!silent) 141 RTE_LOG(INFO, USER1, "Stats is not supported\n"); 142 return -ENOTSUP; 143 } 144 145 if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) && 146 (ipsec_xform->options.iv_gen_disable == 1) && 147 (sec_cap->ipsec.options.iv_gen_disable != 1)) { 148 if (!silent) 149 RTE_LOG(INFO, USER1, 150 "Application provided IV is not supported\n"); 151 return -ENOTSUP; 152 } 153 154 if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 155 (ipsec_xform->options.tunnel_hdr_verify > 156 sec_cap->ipsec.options.tunnel_hdr_verify)) { 157 if (!silent) 158 RTE_LOG(INFO, USER1, 159 "Tunnel header verify is not supported\n"); 160 return -ENOTSUP; 161 } 162 163 if (ipsec_xform->options.ip_csum_enable == 1 && 164 sec_cap->ipsec.options.ip_csum_enable == 0) { 165 if (!silent) 166 RTE_LOG(INFO, USER1, 167 "Inner IP checksum is not supported\n"); 168 return -ENOTSUP; 169 } 170 171 if (ipsec_xform->options.l4_csum_enable == 1 && 172 sec_cap->ipsec.options.l4_csum_enable == 0) { 173 if (!silent) 174 RTE_LOG(INFO, USER1, 175 "Inner L4 checksum is not supported\n"); 176 return -ENOTSUP; 177 } 178 179 return 0; 180 } 181 182 int 183 test_ipsec_crypto_caps_aead_verify( 184 const struct rte_security_capability *sec_cap, 185 struct rte_crypto_sym_xform *aead) 186 { 187 const struct rte_cryptodev_symmetric_capability *sym_cap; 188 const struct rte_cryptodev_capabilities *crypto_cap; 189 int j = 0; 190 191 while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op != 192 RTE_CRYPTO_OP_TYPE_UNDEFINED) { 193 if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC && 194 crypto_cap->sym.xform_type == aead->type && 195 crypto_cap->sym.aead.algo == aead->aead.algo) { 196 sym_cap = &crypto_cap->sym; 197 if (rte_cryptodev_sym_capability_check_aead(sym_cap, 198 aead->aead.key.length, 199 aead->aead.digest_length, 200 aead->aead.aad_length, 201 aead->aead.iv.length) == 0) 202 return 0; 203 } 204 } 205 206 return -ENOTSUP; 207 } 208 209 int 210 test_ipsec_crypto_caps_cipher_verify( 211 const struct rte_security_capability *sec_cap, 212 struct rte_crypto_sym_xform *cipher) 213 { 214 const struct rte_cryptodev_symmetric_capability *sym_cap; 215 const struct rte_cryptodev_capabilities *cap; 216 int j = 0; 217 218 while ((cap = &sec_cap->crypto_capabilities[j++])->op != 219 RTE_CRYPTO_OP_TYPE_UNDEFINED) { 220 if (cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC && 221 cap->sym.xform_type == cipher->type && 222 cap->sym.cipher.algo == cipher->cipher.algo) { 223 sym_cap = &cap->sym; 224 if (rte_cryptodev_sym_capability_check_cipher(sym_cap, 225 cipher->cipher.key.length, 226 cipher->cipher.iv.length) == 0) 227 return 0; 228 } 229 } 230 231 return -ENOTSUP; 232 } 233 234 int 235 test_ipsec_crypto_caps_auth_verify( 236 const struct rte_security_capability *sec_cap, 237 struct rte_crypto_sym_xform *auth) 238 { 239 const struct rte_cryptodev_symmetric_capability *sym_cap; 240 const struct rte_cryptodev_capabilities *cap; 241 int j = 0; 242 243 while ((cap = &sec_cap->crypto_capabilities[j++])->op != 244 RTE_CRYPTO_OP_TYPE_UNDEFINED) { 245 if (cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC && 246 cap->sym.xform_type == auth->type && 247 cap->sym.auth.algo == auth->auth.algo) { 248 sym_cap = &cap->sym; 249 if (rte_cryptodev_sym_capability_check_auth(sym_cap, 250 auth->auth.key.length, 251 auth->auth.digest_length, 252 auth->auth.iv.length) == 0) 253 return 0; 254 } 255 } 256 257 return -ENOTSUP; 258 } 259 260 void 261 test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out, 262 struct ipsec_test_data *td_in) 263 { 264 memcpy(td_in, td_out, sizeof(*td_in)); 265 266 /* Populate output text of td_in with input text of td_out */ 267 memcpy(td_in->output_text.data, td_out->input_text.data, 268 td_out->input_text.len); 269 td_in->output_text.len = td_out->input_text.len; 270 271 /* Populate input text of td_in with output text of td_out */ 272 memcpy(td_in->input_text.data, td_out->output_text.data, 273 td_out->output_text.len); 274 td_in->input_text.len = td_out->output_text.len; 275 276 td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; 277 278 if (td_in->aead) { 279 td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT; 280 } else { 281 td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; 282 td_in->xform.chain.cipher.cipher.op = 283 RTE_CRYPTO_CIPHER_OP_DECRYPT; 284 } 285 } 286 287 static bool 288 is_ipv4(void *ip) 289 { 290 struct rte_ipv4_hdr *ipv4 = ip; 291 uint8_t ip_ver; 292 293 ip_ver = (ipv4->version_ihl & 0xf0) >> RTE_IPV4_IHL_MULTIPLIER; 294 if (ip_ver == IPVERSION) 295 return true; 296 else 297 return false; 298 } 299 300 static void 301 test_ipsec_csum_init(void *ip, bool l3, bool l4) 302 { 303 struct rte_ipv4_hdr *ipv4; 304 struct rte_tcp_hdr *tcp; 305 struct rte_udp_hdr *udp; 306 uint8_t next_proto; 307 uint8_t size; 308 309 if (is_ipv4(ip)) { 310 ipv4 = ip; 311 size = sizeof(struct rte_ipv4_hdr); 312 next_proto = ipv4->next_proto_id; 313 314 if (l3) 315 ipv4->hdr_checksum = 0; 316 } else { 317 size = sizeof(struct rte_ipv6_hdr); 318 next_proto = ((struct rte_ipv6_hdr *)ip)->proto; 319 } 320 321 if (l4) { 322 switch (next_proto) { 323 case IPPROTO_TCP: 324 tcp = (struct rte_tcp_hdr *)RTE_PTR_ADD(ip, size); 325 tcp->cksum = 0; 326 break; 327 case IPPROTO_UDP: 328 udp = (struct rte_udp_hdr *)RTE_PTR_ADD(ip, size); 329 udp->dgram_cksum = 0; 330 break; 331 default: 332 return; 333 } 334 } 335 } 336 337 void 338 test_ipsec_td_prepare(const struct crypto_param *param1, 339 const struct crypto_param *param2, 340 const struct ipsec_test_flags *flags, 341 struct ipsec_test_data *td_array, 342 int nb_td) 343 344 { 345 struct ipsec_test_data *td; 346 int i; 347 348 memset(td_array, 0, nb_td * sizeof(*td)); 349 350 for (i = 0; i < nb_td; i++) { 351 td = &td_array[i]; 352 353 /* Prepare fields based on param */ 354 355 if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) { 356 /* Copy template for packet & key fields */ 357 if (flags->ipv6) 358 memcpy(td, &pkt_aes_256_gcm_v6, sizeof(*td)); 359 else 360 memcpy(td, &pkt_aes_256_gcm, sizeof(*td)); 361 362 td->aead = true; 363 td->xform.aead.aead.algo = param1->alg.aead; 364 td->xform.aead.aead.key.length = param1->key_length; 365 } else { 366 /* Copy template for packet & key fields */ 367 if (flags->ipv6) 368 memcpy(td, &pkt_aes_128_cbc_hmac_sha256_v6, 369 sizeof(*td)); 370 else 371 memcpy(td, &pkt_aes_128_cbc_hmac_sha256, 372 sizeof(*td)); 373 374 td->aead = false; 375 td->xform.chain.cipher.cipher.algo = param1->alg.cipher; 376 td->xform.chain.cipher.cipher.key.length = 377 param1->key_length; 378 td->xform.chain.auth.auth.algo = param2->alg.auth; 379 td->xform.chain.auth.auth.key.length = 380 param2->key_length; 381 td->xform.chain.auth.auth.digest_length = 382 param2->digest_length; 383 384 } 385 386 if (flags->iv_gen) 387 td->ipsec_xform.options.iv_gen_disable = 0; 388 389 if (flags->sa_expiry_pkts_soft) 390 td->ipsec_xform.life.packets_soft_limit = 391 IPSEC_TEST_PACKETS_MAX - 1; 392 393 if (flags->ip_csum) { 394 td->ipsec_xform.options.ip_csum_enable = 1; 395 test_ipsec_csum_init(&td->input_text.data, true, false); 396 } 397 398 if (flags->l4_csum) { 399 td->ipsec_xform.options.l4_csum_enable = 1; 400 test_ipsec_csum_init(&td->input_text.data, false, true); 401 } 402 403 if (flags->tunnel_ipv6) 404 td->ipsec_xform.tunnel.type = 405 RTE_SECURITY_IPSEC_TUNNEL_IPV6; 406 else 407 td->ipsec_xform.tunnel.type = 408 RTE_SECURITY_IPSEC_TUNNEL_IPV4; 409 410 } 411 } 412 413 void 414 test_ipsec_td_update(struct ipsec_test_data td_inb[], 415 const struct ipsec_test_data td_outb[], 416 int nb_td, 417 const struct ipsec_test_flags *flags) 418 { 419 int i; 420 421 for (i = 0; i < nb_td; i++) { 422 memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data, 423 td_outb[i].input_text.len); 424 td_inb[i].output_text.len = td_outb->input_text.len; 425 426 if (flags->icv_corrupt) { 427 int icv_pos = td_inb[i].input_text.len - 4; 428 td_inb[i].input_text.data[icv_pos] += 1; 429 } 430 431 if (flags->sa_expiry_pkts_hard) 432 td_inb[i].ipsec_xform.life.packets_hard_limit = 433 IPSEC_TEST_PACKETS_MAX - 1; 434 435 if (flags->udp_encap) 436 td_inb[i].ipsec_xform.options.udp_encap = 1; 437 438 if (flags->udp_ports_verify) 439 td_inb[i].ipsec_xform.options.udp_ports_verify = 1; 440 441 td_inb[i].ipsec_xform.options.tunnel_hdr_verify = 442 flags->tunnel_hdr_verify; 443 444 if (flags->ip_csum) 445 td_inb[i].ipsec_xform.options.ip_csum_enable = 1; 446 447 if (flags->l4_csum) 448 td_inb[i].ipsec_xform.options.l4_csum_enable = 1; 449 450 /* Clear outbound specific flags */ 451 td_inb[i].ipsec_xform.options.iv_gen_disable = 0; 452 } 453 } 454 455 void 456 test_ipsec_display_alg(const struct crypto_param *param1, 457 const struct crypto_param *param2) 458 { 459 if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) { 460 printf("\t%s [%d]", 461 rte_crypto_aead_algorithm_strings[param1->alg.aead], 462 param1->key_length * 8); 463 } else { 464 printf("\t%s", 465 rte_crypto_cipher_algorithm_strings[param1->alg.cipher]); 466 if (param1->alg.cipher != RTE_CRYPTO_CIPHER_NULL) 467 printf(" [%d]", param1->key_length * 8); 468 printf(" %s", 469 rte_crypto_auth_algorithm_strings[param2->alg.auth]); 470 if (param2->alg.auth != RTE_CRYPTO_AUTH_NULL) 471 printf(" [%dB ICV]", param2->digest_length); 472 } 473 printf("\n"); 474 } 475 476 static int 477 test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td) 478 { 479 int len = 0; 480 481 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 482 if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { 483 if (td->ipsec_xform.tunnel.type == 484 RTE_SECURITY_IPSEC_TUNNEL_IPV4) 485 len += sizeof(struct rte_ipv4_hdr); 486 else 487 len += sizeof(struct rte_ipv6_hdr); 488 } 489 } 490 491 return len; 492 } 493 494 static int 495 test_ipsec_iv_verify_push(struct rte_mbuf *m, const struct ipsec_test_data *td) 496 { 497 static uint8_t iv_queue[IV_LEN_MAX * IPSEC_TEST_PACKETS_MAX]; 498 uint8_t *iv_tmp, *output_text = rte_pktmbuf_mtod(m, uint8_t *); 499 int i, iv_pos, iv_len; 500 static int index; 501 502 if (td->aead) 503 iv_len = td->xform.aead.aead.iv.length - td->salt.len; 504 else 505 iv_len = td->xform.chain.cipher.cipher.iv.length; 506 507 iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr); 508 output_text += iv_pos; 509 510 TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported"); 511 512 /* Compare against previous values */ 513 for (i = 0; i < index; i++) { 514 iv_tmp = &iv_queue[i * IV_LEN_MAX]; 515 516 if (memcmp(output_text, iv_tmp, iv_len) == 0) { 517 printf("IV repeated"); 518 return TEST_FAILED; 519 } 520 } 521 522 /* Save IV for future comparisons */ 523 524 iv_tmp = &iv_queue[index * IV_LEN_MAX]; 525 memcpy(iv_tmp, output_text, iv_len); 526 index++; 527 528 if (index == IPSEC_TEST_PACKETS_MAX) 529 index = 0; 530 531 return TEST_SUCCESS; 532 } 533 534 static int 535 test_ipsec_l3_csum_verify(struct rte_mbuf *m) 536 { 537 uint16_t actual_cksum, expected_cksum; 538 struct rte_ipv4_hdr *ip; 539 540 ip = rte_pktmbuf_mtod(m, struct rte_ipv4_hdr *); 541 542 if (!is_ipv4((void *)ip)) 543 return TEST_SKIPPED; 544 545 actual_cksum = ip->hdr_checksum; 546 547 ip->hdr_checksum = 0; 548 549 expected_cksum = rte_ipv4_cksum(ip); 550 551 if (actual_cksum != expected_cksum) 552 return TEST_FAILED; 553 554 return TEST_SUCCESS; 555 } 556 557 static int 558 test_ipsec_l4_csum_verify(struct rte_mbuf *m) 559 { 560 uint16_t actual_cksum = 0, expected_cksum = 0; 561 struct rte_ipv4_hdr *ipv4; 562 struct rte_ipv6_hdr *ipv6; 563 struct rte_tcp_hdr *tcp; 564 struct rte_udp_hdr *udp; 565 void *ip, *l4; 566 567 ip = rte_pktmbuf_mtod(m, void *); 568 569 if (is_ipv4(ip)) { 570 ipv4 = ip; 571 l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr)); 572 573 switch (ipv4->next_proto_id) { 574 case IPPROTO_TCP: 575 tcp = (struct rte_tcp_hdr *)l4; 576 actual_cksum = tcp->cksum; 577 tcp->cksum = 0; 578 expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4); 579 break; 580 case IPPROTO_UDP: 581 udp = (struct rte_udp_hdr *)l4; 582 actual_cksum = udp->dgram_cksum; 583 udp->dgram_cksum = 0; 584 expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4); 585 break; 586 default: 587 break; 588 } 589 } else { 590 ipv6 = ip; 591 l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr)); 592 593 switch (ipv6->proto) { 594 case IPPROTO_TCP: 595 tcp = (struct rte_tcp_hdr *)l4; 596 actual_cksum = tcp->cksum; 597 tcp->cksum = 0; 598 expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4); 599 break; 600 case IPPROTO_UDP: 601 udp = (struct rte_udp_hdr *)l4; 602 actual_cksum = udp->dgram_cksum; 603 udp->dgram_cksum = 0; 604 expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4); 605 break; 606 default: 607 break; 608 } 609 } 610 611 if (actual_cksum != expected_cksum) 612 return TEST_FAILED; 613 614 return TEST_SUCCESS; 615 } 616 617 static int 618 test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td, 619 bool silent, const struct ipsec_test_flags *flags) 620 { 621 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 622 uint32_t skip, len = rte_pktmbuf_pkt_len(m); 623 int ret; 624 625 /* For tests with status as error for test success, skip verification */ 626 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && 627 (flags->icv_corrupt || 628 flags->sa_expiry_pkts_hard || 629 flags->tunnel_hdr_verify)) 630 return TEST_SUCCESS; 631 632 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS && 633 flags->udp_encap) { 634 const struct rte_ipv4_hdr *iph4; 635 const struct rte_ipv6_hdr *iph6; 636 637 if (td->ipsec_xform.tunnel.type == 638 RTE_SECURITY_IPSEC_TUNNEL_IPV4) { 639 iph4 = (const struct rte_ipv4_hdr *)output_text; 640 if (iph4->next_proto_id != IPPROTO_UDP) { 641 printf("UDP header is not found\n"); 642 return TEST_FAILED; 643 } 644 } else { 645 iph6 = (const struct rte_ipv6_hdr *)output_text; 646 if (iph6->proto != IPPROTO_UDP) { 647 printf("UDP header is not found\n"); 648 return TEST_FAILED; 649 } 650 } 651 652 len -= sizeof(struct rte_udp_hdr); 653 output_text += sizeof(struct rte_udp_hdr); 654 } 655 656 if (len != td->output_text.len) { 657 printf("Output length (%d) not matching with expected (%d)\n", 658 len, td->output_text.len); 659 return TEST_FAILED; 660 } 661 662 skip = test_ipsec_tunnel_hdr_len_get(td); 663 664 len -= skip; 665 output_text += skip; 666 667 if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 668 flags->ip_csum) { 669 if (m->ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD) 670 ret = test_ipsec_l3_csum_verify(m); 671 else 672 ret = TEST_FAILED; 673 674 if (ret == TEST_FAILED) 675 printf("Inner IP checksum test failed\n"); 676 677 return ret; 678 } 679 680 if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 681 flags->l4_csum) { 682 if (m->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD) 683 ret = test_ipsec_l4_csum_verify(m); 684 else 685 ret = TEST_FAILED; 686 687 if (ret == TEST_FAILED) 688 printf("Inner L4 checksum test failed\n"); 689 690 return ret; 691 } 692 693 694 if (memcmp(output_text, td->output_text.data + skip, len)) { 695 if (silent) 696 return TEST_FAILED; 697 698 printf("TestCase %s line %d: %s\n", __func__, __LINE__, 699 "output text not as expected\n"); 700 701 rte_hexdump(stdout, "expected", td->output_text.data + skip, 702 len); 703 rte_hexdump(stdout, "actual", output_text, len); 704 return TEST_FAILED; 705 } 706 707 return TEST_SUCCESS; 708 } 709 710 static int 711 test_ipsec_res_d_prepare(struct rte_mbuf *m, const struct ipsec_test_data *td, 712 struct ipsec_test_data *res_d) 713 { 714 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 715 uint32_t len = rte_pktmbuf_pkt_len(m); 716 717 memcpy(res_d, td, sizeof(*res_d)); 718 memcpy(res_d->input_text.data, output_text, len); 719 res_d->input_text.len = len; 720 721 res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; 722 if (res_d->aead) { 723 res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT; 724 } else { 725 res_d->xform.chain.cipher.cipher.op = 726 RTE_CRYPTO_CIPHER_OP_DECRYPT; 727 res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; 728 } 729 730 return TEST_SUCCESS; 731 } 732 733 int 734 test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td, 735 struct ipsec_test_data *res_d, bool silent, 736 const struct ipsec_test_flags *flags) 737 { 738 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 739 int ret; 740 741 if (flags->iv_gen && 742 td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 743 ret = test_ipsec_iv_verify_push(m, td); 744 if (ret != TEST_SUCCESS) 745 return ret; 746 } 747 748 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 749 const struct rte_ipv4_hdr *iph4; 750 const struct rte_ipv6_hdr *iph6; 751 752 if (td->ipsec_xform.tunnel.type == 753 RTE_SECURITY_IPSEC_TUNNEL_IPV4) { 754 iph4 = (const struct rte_ipv4_hdr *)output_text; 755 if (is_valid_ipv4_pkt(iph4) == false) { 756 printf("Outer header is not IPv4\n"); 757 return TEST_FAILED; 758 } 759 } else { 760 iph6 = (const struct rte_ipv6_hdr *)output_text; 761 if (is_valid_ipv6_pkt(iph6) == false) { 762 printf("Outer header is not IPv6\n"); 763 return TEST_FAILED; 764 } 765 } 766 } 767 768 /* 769 * In case of known vector tests & all inbound tests, res_d provided 770 * would be NULL and output data need to be validated against expected. 771 * For inbound, output_text would be plain packet and for outbound 772 * output_text would IPsec packet. Validate by comparing against 773 * known vectors. 774 * 775 * In case of combined mode tests, the output_text from outbound 776 * operation (ie, IPsec packet) would need to be inbound processed to 777 * obtain the plain text. Copy output_text to result data, 'res_d', so 778 * that inbound processing can be done. 779 */ 780 781 if (res_d == NULL) 782 return test_ipsec_td_verify(m, td, silent, flags); 783 else 784 return test_ipsec_res_d_prepare(m, td, res_d); 785 } 786 787 int 788 test_ipsec_status_check(struct rte_crypto_op *op, 789 const struct ipsec_test_flags *flags, 790 enum rte_security_ipsec_sa_direction dir, 791 int pkt_num) 792 { 793 int ret = TEST_SUCCESS; 794 795 if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && 796 flags->sa_expiry_pkts_hard && 797 pkt_num == IPSEC_TEST_PACKETS_MAX) { 798 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 799 printf("SA hard expiry (pkts) test failed\n"); 800 return TEST_FAILED; 801 } else { 802 return TEST_SUCCESS; 803 } 804 } 805 806 if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 807 flags->tunnel_hdr_verify) { 808 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 809 printf("Tunnel header verify test case failed\n"); 810 return TEST_FAILED; 811 } else { 812 return TEST_SUCCESS; 813 } 814 } 815 816 if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) { 817 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 818 printf("ICV corruption test case failed\n"); 819 ret = TEST_FAILED; 820 } 821 } else { 822 if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) { 823 printf("Security op processing failed [pkt_num: %d]\n", 824 pkt_num); 825 ret = TEST_FAILED; 826 } 827 } 828 829 if (flags->sa_expiry_pkts_soft && pkt_num == IPSEC_TEST_PACKETS_MAX) { 830 if (!(op->aux_flags & 831 RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) { 832 printf("SA soft expiry (pkts) test failed\n"); 833 ret = TEST_FAILED; 834 } 835 } 836 837 return ret; 838 } 839