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