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.cipher.cipher.iv.length = 379 param1->iv_length; 380 td->xform.chain.auth.auth.algo = param2->alg.auth; 381 td->xform.chain.auth.auth.key.length = 382 param2->key_length; 383 td->xform.chain.auth.auth.digest_length = 384 param2->digest_length; 385 386 } 387 388 if (flags->iv_gen) 389 td->ipsec_xform.options.iv_gen_disable = 0; 390 391 if (flags->sa_expiry_pkts_soft) 392 td->ipsec_xform.life.packets_soft_limit = 393 IPSEC_TEST_PACKETS_MAX - 1; 394 395 if (flags->ip_csum) { 396 td->ipsec_xform.options.ip_csum_enable = 1; 397 test_ipsec_csum_init(&td->input_text.data, true, false); 398 } 399 400 if (flags->l4_csum) { 401 td->ipsec_xform.options.l4_csum_enable = 1; 402 test_ipsec_csum_init(&td->input_text.data, false, true); 403 } 404 405 if (flags->transport) { 406 td->ipsec_xform.mode = 407 RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT; 408 } else { 409 td->ipsec_xform.mode = 410 RTE_SECURITY_IPSEC_SA_MODE_TUNNEL; 411 412 if (flags->tunnel_ipv6) 413 td->ipsec_xform.tunnel.type = 414 RTE_SECURITY_IPSEC_TUNNEL_IPV6; 415 else 416 td->ipsec_xform.tunnel.type = 417 RTE_SECURITY_IPSEC_TUNNEL_IPV4; 418 } 419 420 if (flags->stats_success) 421 td->ipsec_xform.options.stats = 1; 422 423 if (flags->fragment) { 424 struct rte_ipv4_hdr *ip; 425 ip = (struct rte_ipv4_hdr *)&td->input_text.data; 426 ip->fragment_offset = 4; 427 ip->hdr_checksum = rte_ipv4_cksum(ip); 428 } 429 430 } 431 } 432 433 void 434 test_ipsec_td_update(struct ipsec_test_data td_inb[], 435 const struct ipsec_test_data td_outb[], 436 int nb_td, 437 const struct ipsec_test_flags *flags) 438 { 439 int i; 440 441 for (i = 0; i < nb_td; i++) { 442 memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data, 443 td_outb[i].input_text.len); 444 td_inb[i].output_text.len = td_outb->input_text.len; 445 446 if (flags->icv_corrupt) { 447 int icv_pos = td_inb[i].input_text.len - 4; 448 td_inb[i].input_text.data[icv_pos] += 1; 449 } 450 451 if (flags->sa_expiry_pkts_hard) 452 td_inb[i].ipsec_xform.life.packets_hard_limit = 453 IPSEC_TEST_PACKETS_MAX - 1; 454 455 if (flags->udp_encap) 456 td_inb[i].ipsec_xform.options.udp_encap = 1; 457 458 if (flags->udp_ports_verify) 459 td_inb[i].ipsec_xform.options.udp_ports_verify = 1; 460 461 td_inb[i].ipsec_xform.options.tunnel_hdr_verify = 462 flags->tunnel_hdr_verify; 463 464 if (flags->ip_csum) 465 td_inb[i].ipsec_xform.options.ip_csum_enable = 1; 466 467 if (flags->l4_csum) 468 td_inb[i].ipsec_xform.options.l4_csum_enable = 1; 469 470 /* Clear outbound specific flags */ 471 td_inb[i].ipsec_xform.options.iv_gen_disable = 0; 472 } 473 } 474 475 void 476 test_ipsec_display_alg(const struct crypto_param *param1, 477 const struct crypto_param *param2) 478 { 479 if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) { 480 printf("\t%s [%d]", 481 rte_crypto_aead_algorithm_strings[param1->alg.aead], 482 param1->key_length * 8); 483 } else { 484 printf("\t%s", 485 rte_crypto_cipher_algorithm_strings[param1->alg.cipher]); 486 if (param1->alg.cipher != RTE_CRYPTO_CIPHER_NULL) 487 printf(" [%d]", param1->key_length * 8); 488 printf(" %s", 489 rte_crypto_auth_algorithm_strings[param2->alg.auth]); 490 if (param2->alg.auth != RTE_CRYPTO_AUTH_NULL) 491 printf(" [%dB ICV]", param2->digest_length); 492 } 493 printf("\n"); 494 } 495 496 static int 497 test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td) 498 { 499 int len = 0; 500 501 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 502 if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { 503 if (td->ipsec_xform.tunnel.type == 504 RTE_SECURITY_IPSEC_TUNNEL_IPV4) 505 len += sizeof(struct rte_ipv4_hdr); 506 else 507 len += sizeof(struct rte_ipv6_hdr); 508 } 509 } 510 511 return len; 512 } 513 514 static int 515 test_ipsec_iv_verify_push(struct rte_mbuf *m, const struct ipsec_test_data *td) 516 { 517 static uint8_t iv_queue[IV_LEN_MAX * IPSEC_TEST_PACKETS_MAX]; 518 uint8_t *iv_tmp, *output_text = rte_pktmbuf_mtod(m, uint8_t *); 519 int i, iv_pos, iv_len; 520 static int index; 521 522 if (td->aead) 523 iv_len = td->xform.aead.aead.iv.length - td->salt.len; 524 else 525 iv_len = td->xform.chain.cipher.cipher.iv.length; 526 527 iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr); 528 output_text += iv_pos; 529 530 TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported"); 531 532 /* Compare against previous values */ 533 for (i = 0; i < index; i++) { 534 iv_tmp = &iv_queue[i * IV_LEN_MAX]; 535 536 if (memcmp(output_text, iv_tmp, iv_len) == 0) { 537 printf("IV repeated"); 538 return TEST_FAILED; 539 } 540 } 541 542 /* Save IV for future comparisons */ 543 544 iv_tmp = &iv_queue[index * IV_LEN_MAX]; 545 memcpy(iv_tmp, output_text, iv_len); 546 index++; 547 548 if (index == IPSEC_TEST_PACKETS_MAX) 549 index = 0; 550 551 return TEST_SUCCESS; 552 } 553 554 static int 555 test_ipsec_l3_csum_verify(struct rte_mbuf *m) 556 { 557 uint16_t actual_cksum, expected_cksum; 558 struct rte_ipv4_hdr *ip; 559 560 ip = rte_pktmbuf_mtod(m, struct rte_ipv4_hdr *); 561 562 if (!is_ipv4((void *)ip)) 563 return TEST_SKIPPED; 564 565 actual_cksum = ip->hdr_checksum; 566 567 ip->hdr_checksum = 0; 568 569 expected_cksum = rte_ipv4_cksum(ip); 570 571 if (actual_cksum != expected_cksum) 572 return TEST_FAILED; 573 574 return TEST_SUCCESS; 575 } 576 577 static int 578 test_ipsec_l4_csum_verify(struct rte_mbuf *m) 579 { 580 uint16_t actual_cksum = 0, expected_cksum = 0; 581 struct rte_ipv4_hdr *ipv4; 582 struct rte_ipv6_hdr *ipv6; 583 struct rte_tcp_hdr *tcp; 584 struct rte_udp_hdr *udp; 585 void *ip, *l4; 586 587 ip = rte_pktmbuf_mtod(m, void *); 588 589 if (is_ipv4(ip)) { 590 ipv4 = ip; 591 l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr)); 592 593 switch (ipv4->next_proto_id) { 594 case IPPROTO_TCP: 595 tcp = (struct rte_tcp_hdr *)l4; 596 actual_cksum = tcp->cksum; 597 tcp->cksum = 0; 598 expected_cksum = rte_ipv4_udptcp_cksum(ipv4, 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_ipv4_udptcp_cksum(ipv4, l4); 605 break; 606 default: 607 break; 608 } 609 } else { 610 ipv6 = ip; 611 l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr)); 612 613 switch (ipv6->proto) { 614 case IPPROTO_TCP: 615 tcp = (struct rte_tcp_hdr *)l4; 616 actual_cksum = tcp->cksum; 617 tcp->cksum = 0; 618 expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4); 619 break; 620 case IPPROTO_UDP: 621 udp = (struct rte_udp_hdr *)l4; 622 actual_cksum = udp->dgram_cksum; 623 udp->dgram_cksum = 0; 624 expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4); 625 break; 626 default: 627 break; 628 } 629 } 630 631 if (actual_cksum != expected_cksum) 632 return TEST_FAILED; 633 634 return TEST_SUCCESS; 635 } 636 637 static int 638 test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td, 639 bool silent, const struct ipsec_test_flags *flags) 640 { 641 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 642 uint32_t skip, len = rte_pktmbuf_pkt_len(m); 643 int ret; 644 645 /* For tests with status as error for test success, skip verification */ 646 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && 647 (flags->icv_corrupt || 648 flags->sa_expiry_pkts_hard || 649 flags->tunnel_hdr_verify)) 650 return TEST_SUCCESS; 651 652 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS && 653 flags->udp_encap) { 654 const struct rte_ipv4_hdr *iph4; 655 const struct rte_ipv6_hdr *iph6; 656 657 if (td->ipsec_xform.tunnel.type == 658 RTE_SECURITY_IPSEC_TUNNEL_IPV4) { 659 iph4 = (const struct rte_ipv4_hdr *)output_text; 660 if (iph4->next_proto_id != IPPROTO_UDP) { 661 printf("UDP header is not found\n"); 662 return TEST_FAILED; 663 } 664 } else { 665 iph6 = (const struct rte_ipv6_hdr *)output_text; 666 if (iph6->proto != IPPROTO_UDP) { 667 printf("UDP header is not found\n"); 668 return TEST_FAILED; 669 } 670 } 671 672 len -= sizeof(struct rte_udp_hdr); 673 output_text += sizeof(struct rte_udp_hdr); 674 } 675 676 if (len != td->output_text.len) { 677 printf("Output length (%d) not matching with expected (%d)\n", 678 len, td->output_text.len); 679 return TEST_FAILED; 680 } 681 682 if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) && 683 flags->fragment) { 684 const struct rte_ipv4_hdr *iph4; 685 iph4 = (const struct rte_ipv4_hdr *)output_text; 686 if (iph4->fragment_offset) { 687 printf("Output packet is fragmented"); 688 return TEST_FAILED; 689 } 690 } 691 692 skip = test_ipsec_tunnel_hdr_len_get(td); 693 694 len -= skip; 695 output_text += skip; 696 697 if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 698 flags->ip_csum) { 699 if (m->ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD) 700 ret = test_ipsec_l3_csum_verify(m); 701 else 702 ret = TEST_FAILED; 703 704 if (ret == TEST_FAILED) 705 printf("Inner IP checksum test failed\n"); 706 707 return ret; 708 } 709 710 if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 711 flags->l4_csum) { 712 if (m->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD) 713 ret = test_ipsec_l4_csum_verify(m); 714 else 715 ret = TEST_FAILED; 716 717 if (ret == TEST_FAILED) 718 printf("Inner L4 checksum test failed\n"); 719 720 return ret; 721 } 722 723 724 if (memcmp(output_text, td->output_text.data + skip, len)) { 725 if (silent) 726 return TEST_FAILED; 727 728 printf("TestCase %s line %d: %s\n", __func__, __LINE__, 729 "output text not as expected\n"); 730 731 rte_hexdump(stdout, "expected", td->output_text.data + skip, 732 len); 733 rte_hexdump(stdout, "actual", output_text, len); 734 return TEST_FAILED; 735 } 736 737 return TEST_SUCCESS; 738 } 739 740 static int 741 test_ipsec_res_d_prepare(struct rte_mbuf *m, const struct ipsec_test_data *td, 742 struct ipsec_test_data *res_d) 743 { 744 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 745 uint32_t len = rte_pktmbuf_pkt_len(m); 746 747 memcpy(res_d, td, sizeof(*res_d)); 748 memcpy(res_d->input_text.data, output_text, len); 749 res_d->input_text.len = len; 750 751 res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; 752 if (res_d->aead) { 753 res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT; 754 } else { 755 res_d->xform.chain.cipher.cipher.op = 756 RTE_CRYPTO_CIPHER_OP_DECRYPT; 757 res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; 758 } 759 760 return TEST_SUCCESS; 761 } 762 763 int 764 test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td, 765 struct ipsec_test_data *res_d, bool silent, 766 const struct ipsec_test_flags *flags) 767 { 768 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 769 int ret; 770 771 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 772 const struct rte_ipv4_hdr *iph4; 773 const struct rte_ipv6_hdr *iph6; 774 775 if (flags->iv_gen) { 776 ret = test_ipsec_iv_verify_push(m, td); 777 if (ret != TEST_SUCCESS) 778 return ret; 779 } 780 781 iph4 = (const struct rte_ipv4_hdr *)output_text; 782 783 if (td->ipsec_xform.mode == 784 RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) { 785 if (flags->ipv6) { 786 iph6 = (const struct rte_ipv6_hdr *)output_text; 787 if (is_valid_ipv6_pkt(iph6) == false) { 788 printf("Transport packet is not IPv6\n"); 789 return TEST_FAILED; 790 } 791 } else { 792 if (is_valid_ipv4_pkt(iph4) == false) { 793 printf("Transport packet is not IPv4\n"); 794 return TEST_FAILED; 795 } 796 } 797 } else { 798 if (td->ipsec_xform.tunnel.type == 799 RTE_SECURITY_IPSEC_TUNNEL_IPV4) { 800 if (is_valid_ipv4_pkt(iph4) == false) { 801 printf("Tunnel outer header is not IPv4\n"); 802 return TEST_FAILED; 803 } 804 } else { 805 iph6 = (const struct rte_ipv6_hdr *)output_text; 806 if (is_valid_ipv6_pkt(iph6) == false) { 807 printf("Tunnel outer header is not IPv6\n"); 808 return TEST_FAILED; 809 } 810 } 811 } 812 } 813 814 /* 815 * In case of known vector tests & all inbound tests, res_d provided 816 * would be NULL and output data need to be validated against expected. 817 * For inbound, output_text would be plain packet and for outbound 818 * output_text would IPsec packet. Validate by comparing against 819 * known vectors. 820 * 821 * In case of combined mode tests, the output_text from outbound 822 * operation (ie, IPsec packet) would need to be inbound processed to 823 * obtain the plain text. Copy output_text to result data, 'res_d', so 824 * that inbound processing can be done. 825 */ 826 827 if (res_d == NULL) 828 return test_ipsec_td_verify(m, td, silent, flags); 829 else 830 return test_ipsec_res_d_prepare(m, td, res_d); 831 } 832 833 int 834 test_ipsec_status_check(struct rte_crypto_op *op, 835 const struct ipsec_test_flags *flags, 836 enum rte_security_ipsec_sa_direction dir, 837 int pkt_num) 838 { 839 int ret = TEST_SUCCESS; 840 841 if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && 842 flags->sa_expiry_pkts_hard && 843 pkt_num == IPSEC_TEST_PACKETS_MAX) { 844 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 845 printf("SA hard expiry (pkts) test failed\n"); 846 return TEST_FAILED; 847 } else { 848 return TEST_SUCCESS; 849 } 850 } 851 852 if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 853 flags->tunnel_hdr_verify) { 854 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 855 printf("Tunnel header verify test case failed\n"); 856 return TEST_FAILED; 857 } else { 858 return TEST_SUCCESS; 859 } 860 } 861 862 if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) { 863 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 864 printf("ICV corruption test case failed\n"); 865 ret = TEST_FAILED; 866 } 867 } else { 868 if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) { 869 printf("Security op processing failed [pkt_num: %d]\n", 870 pkt_num); 871 ret = TEST_FAILED; 872 } 873 } 874 875 if (flags->sa_expiry_pkts_soft && pkt_num == IPSEC_TEST_PACKETS_MAX) { 876 if (!(op->aux_flags & 877 RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) { 878 printf("SA soft expiry (pkts) test failed\n"); 879 ret = TEST_FAILED; 880 } 881 } 882 883 return ret; 884 } 885 886 int 887 test_ipsec_stats_verify(struct rte_security_ctx *ctx, 888 struct rte_security_session *sess, 889 const struct ipsec_test_flags *flags, 890 enum rte_security_ipsec_sa_direction dir) 891 { 892 struct rte_security_stats stats = {0}; 893 int ret = TEST_SUCCESS; 894 895 if (flags->stats_success) { 896 if (rte_security_session_stats_get(ctx, sess, &stats) < 0) 897 return TEST_FAILED; 898 899 if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 900 if (stats.ipsec.opackets != 1 || 901 stats.ipsec.oerrors != 0) 902 ret = TEST_FAILED; 903 } else { 904 if (stats.ipsec.ipackets != 1 || 905 stats.ipsec.ierrors != 0) 906 ret = TEST_FAILED; 907 } 908 } 909 910 return ret; 911 } 912