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 if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 || 437 flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1) 438 td->ipsec_xform.options.copy_dscp = 1; 439 } 440 } 441 442 void 443 test_ipsec_td_update(struct ipsec_test_data td_inb[], 444 const struct ipsec_test_data td_outb[], 445 int nb_td, 446 const struct ipsec_test_flags *flags) 447 { 448 int i; 449 450 for (i = 0; i < nb_td; i++) { 451 memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data, 452 td_outb[i].input_text.len); 453 td_inb[i].output_text.len = td_outb->input_text.len; 454 455 if (flags->icv_corrupt) { 456 int icv_pos = td_inb[i].input_text.len - 4; 457 td_inb[i].input_text.data[icv_pos] += 1; 458 } 459 460 if (flags->sa_expiry_pkts_hard) 461 td_inb[i].ipsec_xform.life.packets_hard_limit = 462 IPSEC_TEST_PACKETS_MAX - 1; 463 464 if (flags->udp_encap) 465 td_inb[i].ipsec_xform.options.udp_encap = 1; 466 467 if (flags->udp_ports_verify) 468 td_inb[i].ipsec_xform.options.udp_ports_verify = 1; 469 470 td_inb[i].ipsec_xform.options.tunnel_hdr_verify = 471 flags->tunnel_hdr_verify; 472 473 if (flags->ip_csum) 474 td_inb[i].ipsec_xform.options.ip_csum_enable = 1; 475 476 if (flags->l4_csum) 477 td_inb[i].ipsec_xform.options.l4_csum_enable = 1; 478 479 /* Clear outbound specific flags */ 480 td_inb[i].ipsec_xform.options.iv_gen_disable = 0; 481 } 482 } 483 484 void 485 test_ipsec_display_alg(const struct crypto_param *param1, 486 const struct crypto_param *param2) 487 { 488 if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) { 489 printf("\t%s [%d]", 490 rte_crypto_aead_algorithm_strings[param1->alg.aead], 491 param1->key_length * 8); 492 } else { 493 printf("\t%s", 494 rte_crypto_cipher_algorithm_strings[param1->alg.cipher]); 495 if (param1->alg.cipher != RTE_CRYPTO_CIPHER_NULL) 496 printf(" [%d]", param1->key_length * 8); 497 printf(" %s", 498 rte_crypto_auth_algorithm_strings[param2->alg.auth]); 499 if (param2->alg.auth != RTE_CRYPTO_AUTH_NULL) 500 printf(" [%dB ICV]", param2->digest_length); 501 } 502 printf("\n"); 503 } 504 505 static int 506 test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td) 507 { 508 int len = 0; 509 510 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 511 if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { 512 if (td->ipsec_xform.tunnel.type == 513 RTE_SECURITY_IPSEC_TUNNEL_IPV4) 514 len += sizeof(struct rte_ipv4_hdr); 515 else 516 len += sizeof(struct rte_ipv6_hdr); 517 } 518 } 519 520 return len; 521 } 522 523 static int 524 test_ipsec_iv_verify_push(struct rte_mbuf *m, const struct ipsec_test_data *td) 525 { 526 static uint8_t iv_queue[IV_LEN_MAX * IPSEC_TEST_PACKETS_MAX]; 527 uint8_t *iv_tmp, *output_text = rte_pktmbuf_mtod(m, uint8_t *); 528 int i, iv_pos, iv_len; 529 static int index; 530 531 if (td->aead) 532 iv_len = td->xform.aead.aead.iv.length - td->salt.len; 533 else 534 iv_len = td->xform.chain.cipher.cipher.iv.length; 535 536 iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr); 537 output_text += iv_pos; 538 539 TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported"); 540 541 /* Compare against previous values */ 542 for (i = 0; i < index; i++) { 543 iv_tmp = &iv_queue[i * IV_LEN_MAX]; 544 545 if (memcmp(output_text, iv_tmp, iv_len) == 0) { 546 printf("IV repeated"); 547 return TEST_FAILED; 548 } 549 } 550 551 /* Save IV for future comparisons */ 552 553 iv_tmp = &iv_queue[index * IV_LEN_MAX]; 554 memcpy(iv_tmp, output_text, iv_len); 555 index++; 556 557 if (index == IPSEC_TEST_PACKETS_MAX) 558 index = 0; 559 560 return TEST_SUCCESS; 561 } 562 563 static int 564 test_ipsec_l3_csum_verify(struct rte_mbuf *m) 565 { 566 uint16_t actual_cksum, expected_cksum; 567 struct rte_ipv4_hdr *ip; 568 569 ip = rte_pktmbuf_mtod(m, struct rte_ipv4_hdr *); 570 571 if (!is_ipv4((void *)ip)) 572 return TEST_SKIPPED; 573 574 actual_cksum = ip->hdr_checksum; 575 576 ip->hdr_checksum = 0; 577 578 expected_cksum = rte_ipv4_cksum(ip); 579 580 if (actual_cksum != expected_cksum) 581 return TEST_FAILED; 582 583 return TEST_SUCCESS; 584 } 585 586 static int 587 test_ipsec_l4_csum_verify(struct rte_mbuf *m) 588 { 589 uint16_t actual_cksum = 0, expected_cksum = 0; 590 struct rte_ipv4_hdr *ipv4; 591 struct rte_ipv6_hdr *ipv6; 592 struct rte_tcp_hdr *tcp; 593 struct rte_udp_hdr *udp; 594 void *ip, *l4; 595 596 ip = rte_pktmbuf_mtod(m, void *); 597 598 if (is_ipv4(ip)) { 599 ipv4 = ip; 600 l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr)); 601 602 switch (ipv4->next_proto_id) { 603 case IPPROTO_TCP: 604 tcp = (struct rte_tcp_hdr *)l4; 605 actual_cksum = tcp->cksum; 606 tcp->cksum = 0; 607 expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4); 608 break; 609 case IPPROTO_UDP: 610 udp = (struct rte_udp_hdr *)l4; 611 actual_cksum = udp->dgram_cksum; 612 udp->dgram_cksum = 0; 613 expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4); 614 break; 615 default: 616 break; 617 } 618 } else { 619 ipv6 = ip; 620 l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr)); 621 622 switch (ipv6->proto) { 623 case IPPROTO_TCP: 624 tcp = (struct rte_tcp_hdr *)l4; 625 actual_cksum = tcp->cksum; 626 tcp->cksum = 0; 627 expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4); 628 break; 629 case IPPROTO_UDP: 630 udp = (struct rte_udp_hdr *)l4; 631 actual_cksum = udp->dgram_cksum; 632 udp->dgram_cksum = 0; 633 expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4); 634 break; 635 default: 636 break; 637 } 638 } 639 640 if (actual_cksum != expected_cksum) 641 return TEST_FAILED; 642 643 return TEST_SUCCESS; 644 } 645 646 static int 647 test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td, 648 bool silent, const struct ipsec_test_flags *flags) 649 { 650 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 651 uint32_t skip, len = rte_pktmbuf_pkt_len(m); 652 uint8_t td_output_text[4096]; 653 int ret; 654 655 /* For tests with status as error for test success, skip verification */ 656 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && 657 (flags->icv_corrupt || 658 flags->sa_expiry_pkts_hard || 659 flags->tunnel_hdr_verify)) 660 return TEST_SUCCESS; 661 662 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS && 663 flags->udp_encap) { 664 const struct rte_ipv4_hdr *iph4; 665 const struct rte_ipv6_hdr *iph6; 666 667 if (td->ipsec_xform.tunnel.type == 668 RTE_SECURITY_IPSEC_TUNNEL_IPV4) { 669 iph4 = (const struct rte_ipv4_hdr *)output_text; 670 if (iph4->next_proto_id != IPPROTO_UDP) { 671 printf("UDP header is not found\n"); 672 return TEST_FAILED; 673 } 674 } else { 675 iph6 = (const struct rte_ipv6_hdr *)output_text; 676 if (iph6->proto != IPPROTO_UDP) { 677 printf("UDP header is not found\n"); 678 return TEST_FAILED; 679 } 680 } 681 682 len -= sizeof(struct rte_udp_hdr); 683 output_text += sizeof(struct rte_udp_hdr); 684 } 685 686 if (len != td->output_text.len) { 687 printf("Output length (%d) not matching with expected (%d)\n", 688 len, td->output_text.len); 689 return TEST_FAILED; 690 } 691 692 if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) && 693 flags->fragment) { 694 const struct rte_ipv4_hdr *iph4; 695 iph4 = (const struct rte_ipv4_hdr *)output_text; 696 if (iph4->fragment_offset) { 697 printf("Output packet is fragmented"); 698 return TEST_FAILED; 699 } 700 } 701 702 skip = test_ipsec_tunnel_hdr_len_get(td); 703 704 len -= skip; 705 output_text += skip; 706 707 if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 708 flags->ip_csum) { 709 if (m->ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD) 710 ret = test_ipsec_l3_csum_verify(m); 711 else 712 ret = TEST_FAILED; 713 714 if (ret == TEST_FAILED) 715 printf("Inner IP checksum test failed\n"); 716 717 return ret; 718 } 719 720 if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 721 flags->l4_csum) { 722 if (m->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD) 723 ret = test_ipsec_l4_csum_verify(m); 724 else 725 ret = TEST_FAILED; 726 727 if (ret == TEST_FAILED) 728 printf("Inner L4 checksum test failed\n"); 729 730 return ret; 731 } 732 733 memcpy(td_output_text, td->output_text.data + skip, len); 734 735 if (test_ipsec_pkt_update(td_output_text, flags)) { 736 printf("Could not update expected vector"); 737 return TEST_FAILED; 738 } 739 740 if (memcmp(output_text, td_output_text, len)) { 741 if (silent) 742 return TEST_FAILED; 743 744 printf("TestCase %s line %d: %s\n", __func__, __LINE__, 745 "output text not as expected\n"); 746 747 rte_hexdump(stdout, "expected", td_output_text, len); 748 rte_hexdump(stdout, "actual", output_text, len); 749 return TEST_FAILED; 750 } 751 752 return TEST_SUCCESS; 753 } 754 755 static int 756 test_ipsec_res_d_prepare(struct rte_mbuf *m, const struct ipsec_test_data *td, 757 struct ipsec_test_data *res_d) 758 { 759 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 760 uint32_t len = rte_pktmbuf_pkt_len(m); 761 762 memcpy(res_d, td, sizeof(*res_d)); 763 memcpy(res_d->input_text.data, output_text, len); 764 res_d->input_text.len = len; 765 766 res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; 767 if (res_d->aead) { 768 res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT; 769 } else { 770 res_d->xform.chain.cipher.cipher.op = 771 RTE_CRYPTO_CIPHER_OP_DECRYPT; 772 res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; 773 } 774 775 return TEST_SUCCESS; 776 } 777 778 static int 779 test_ipsec_iph4_hdr_validate(const struct rte_ipv4_hdr *iph4, 780 const struct ipsec_test_flags *flags) 781 { 782 uint8_t tos, dscp; 783 uint16_t f_off; 784 785 if (!is_valid_ipv4_pkt(iph4)) { 786 printf("Tunnel outer header is not IPv4\n"); 787 return -1; 788 } 789 790 f_off = rte_be_to_cpu_16(iph4->fragment_offset); 791 if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 || 792 flags->df == TEST_IPSEC_SET_DF_1_INNER_0) { 793 if (!(f_off & RTE_IPV4_HDR_DF_FLAG)) { 794 printf("DF bit is not set\n"); 795 return -1; 796 } 797 } else { 798 if (f_off & RTE_IPV4_HDR_DF_FLAG) { 799 printf("DF bit is set\n"); 800 return -1; 801 } 802 } 803 804 tos = iph4->type_of_service; 805 dscp = (tos & RTE_IPV4_HDR_DSCP_MASK) >> 2; 806 807 if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 || 808 flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) { 809 if (dscp != TEST_IPSEC_DSCP_VAL) { 810 printf("DSCP value is not matching [exp: %x, actual: %x]\n", 811 TEST_IPSEC_DSCP_VAL, dscp); 812 return -1; 813 } 814 } else { 815 if (dscp != 0) { 816 printf("DSCP value is set [exp: 0, actual: %x]\n", 817 dscp); 818 return -1; 819 } 820 } 821 822 return 0; 823 } 824 825 static int 826 test_ipsec_iph6_hdr_validate(const struct rte_ipv6_hdr *iph6, 827 const struct ipsec_test_flags *flags) 828 { 829 uint32_t vtc_flow; 830 uint8_t dscp; 831 832 if (!is_valid_ipv6_pkt(iph6)) { 833 printf("Tunnel outer header is not IPv6\n"); 834 return -1; 835 } 836 837 vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow); 838 dscp = (vtc_flow & RTE_IPV6_HDR_DSCP_MASK) >> 839 (RTE_IPV6_HDR_TC_SHIFT + 2); 840 841 if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 || 842 flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) { 843 if (dscp != TEST_IPSEC_DSCP_VAL) { 844 printf("DSCP value is not matching [exp: %x, actual: %x]\n", 845 TEST_IPSEC_DSCP_VAL, dscp); 846 return -1; 847 } 848 } else { 849 if (dscp != 0) { 850 printf("DSCP value is set [exp: 0, actual: %x]\n", 851 dscp); 852 return -1; 853 } 854 } 855 856 return 0; 857 } 858 859 int 860 test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td, 861 struct ipsec_test_data *res_d, bool silent, 862 const struct ipsec_test_flags *flags) 863 { 864 uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 865 int ret; 866 867 if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 868 const struct rte_ipv4_hdr *iph4; 869 const struct rte_ipv6_hdr *iph6; 870 871 if (flags->iv_gen) { 872 ret = test_ipsec_iv_verify_push(m, td); 873 if (ret != TEST_SUCCESS) 874 return ret; 875 } 876 877 iph4 = (const struct rte_ipv4_hdr *)output_text; 878 879 if (td->ipsec_xform.mode == 880 RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) { 881 if (flags->ipv6) { 882 iph6 = (const struct rte_ipv6_hdr *)output_text; 883 if (is_valid_ipv6_pkt(iph6) == false) { 884 printf("Transport packet is not IPv6\n"); 885 return TEST_FAILED; 886 } 887 } else { 888 if (is_valid_ipv4_pkt(iph4) == false) { 889 printf("Transport packet is not IPv4\n"); 890 return TEST_FAILED; 891 } 892 } 893 } else { 894 if (td->ipsec_xform.tunnel.type == 895 RTE_SECURITY_IPSEC_TUNNEL_IPV4) { 896 if (test_ipsec_iph4_hdr_validate(iph4, flags)) 897 return TEST_FAILED; 898 } else { 899 iph6 = (const struct rte_ipv6_hdr *)output_text; 900 if (test_ipsec_iph6_hdr_validate(iph6, flags)) 901 return TEST_FAILED; 902 } 903 } 904 } 905 906 /* 907 * In case of known vector tests & all inbound tests, res_d provided 908 * would be NULL and output data need to be validated against expected. 909 * For inbound, output_text would be plain packet and for outbound 910 * output_text would IPsec packet. Validate by comparing against 911 * known vectors. 912 * 913 * In case of combined mode tests, the output_text from outbound 914 * operation (ie, IPsec packet) would need to be inbound processed to 915 * obtain the plain text. Copy output_text to result data, 'res_d', so 916 * that inbound processing can be done. 917 */ 918 919 if (res_d == NULL) 920 return test_ipsec_td_verify(m, td, silent, flags); 921 else 922 return test_ipsec_res_d_prepare(m, td, res_d); 923 } 924 925 int 926 test_ipsec_status_check(struct rte_crypto_op *op, 927 const struct ipsec_test_flags *flags, 928 enum rte_security_ipsec_sa_direction dir, 929 int pkt_num) 930 { 931 int ret = TEST_SUCCESS; 932 933 if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && 934 flags->sa_expiry_pkts_hard && 935 pkt_num == IPSEC_TEST_PACKETS_MAX) { 936 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 937 printf("SA hard expiry (pkts) test failed\n"); 938 return TEST_FAILED; 939 } else { 940 return TEST_SUCCESS; 941 } 942 } 943 944 if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 945 flags->tunnel_hdr_verify) { 946 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 947 printf("Tunnel header verify test case failed\n"); 948 return TEST_FAILED; 949 } else { 950 return TEST_SUCCESS; 951 } 952 } 953 954 if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) { 955 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 956 printf("ICV corruption test case failed\n"); 957 ret = TEST_FAILED; 958 } 959 } else { 960 if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) { 961 printf("Security op processing failed [pkt_num: %d]\n", 962 pkt_num); 963 ret = TEST_FAILED; 964 } 965 } 966 967 if (flags->sa_expiry_pkts_soft && pkt_num == IPSEC_TEST_PACKETS_MAX) { 968 if (!(op->aux_flags & 969 RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) { 970 printf("SA soft expiry (pkts) test failed\n"); 971 ret = TEST_FAILED; 972 } 973 } 974 975 return ret; 976 } 977 978 int 979 test_ipsec_stats_verify(struct rte_security_ctx *ctx, 980 struct rte_security_session *sess, 981 const struct ipsec_test_flags *flags, 982 enum rte_security_ipsec_sa_direction dir) 983 { 984 struct rte_security_stats stats = {0}; 985 int ret = TEST_SUCCESS; 986 987 if (flags->stats_success) { 988 if (rte_security_session_stats_get(ctx, sess, &stats) < 0) 989 return TEST_FAILED; 990 991 if (dir == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 992 if (stats.ipsec.opackets != 1 || 993 stats.ipsec.oerrors != 0) 994 ret = TEST_FAILED; 995 } else { 996 if (stats.ipsec.ipackets != 1 || 997 stats.ipsec.ierrors != 0) 998 ret = TEST_FAILED; 999 } 1000 } 1001 1002 return ret; 1003 } 1004 1005 int 1006 test_ipsec_pkt_update(uint8_t *pkt, const struct ipsec_test_flags *flags) 1007 { 1008 struct rte_ipv4_hdr *iph4; 1009 struct rte_ipv6_hdr *iph6; 1010 bool cksum_dirty = false; 1011 1012 iph4 = (struct rte_ipv4_hdr *)pkt; 1013 1014 if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 || 1015 flags->df == TEST_IPSEC_SET_DF_0_INNER_1 || 1016 flags->df == TEST_IPSEC_COPY_DF_INNER_0 || 1017 flags->df == TEST_IPSEC_SET_DF_1_INNER_0) { 1018 uint16_t frag_off; 1019 1020 if (!is_ipv4(iph4)) { 1021 printf("Invalid packet type\n"); 1022 return -1; 1023 } 1024 1025 frag_off = rte_be_to_cpu_16(iph4->fragment_offset); 1026 1027 if (flags->df == TEST_IPSEC_COPY_DF_INNER_1 || 1028 flags->df == TEST_IPSEC_SET_DF_0_INNER_1) 1029 frag_off |= RTE_IPV4_HDR_DF_FLAG; 1030 else 1031 frag_off &= ~RTE_IPV4_HDR_DF_FLAG; 1032 1033 iph4->fragment_offset = rte_cpu_to_be_16(frag_off); 1034 cksum_dirty = true; 1035 } 1036 1037 if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 || 1038 flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1 || 1039 flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_0 || 1040 flags->dscp == TEST_IPSEC_SET_DSCP_1_INNER_0) { 1041 1042 if (is_ipv4(iph4)) { 1043 uint8_t tos; 1044 1045 tos = iph4->type_of_service; 1046 if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 || 1047 flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1) 1048 tos |= (RTE_IPV4_HDR_DSCP_MASK & 1049 (TEST_IPSEC_DSCP_VAL << 2)); 1050 else 1051 tos &= ~RTE_IPV4_HDR_DSCP_MASK; 1052 1053 iph4->type_of_service = tos; 1054 cksum_dirty = true; 1055 } else { 1056 uint32_t vtc_flow; 1057 1058 iph6 = (struct rte_ipv6_hdr *)pkt; 1059 1060 vtc_flow = rte_be_to_cpu_32(iph6->vtc_flow); 1061 if (flags->dscp == TEST_IPSEC_COPY_DSCP_INNER_1 || 1062 flags->dscp == TEST_IPSEC_SET_DSCP_0_INNER_1) 1063 vtc_flow |= (RTE_IPV6_HDR_DSCP_MASK & 1064 (TEST_IPSEC_DSCP_VAL << (RTE_IPV6_HDR_TC_SHIFT + 2))); 1065 else 1066 vtc_flow &= ~RTE_IPV6_HDR_DSCP_MASK; 1067 1068 iph6->vtc_flow = rte_cpu_to_be_32(vtc_flow); 1069 } 1070 } 1071 1072 if (cksum_dirty && is_ipv4(iph4)) { 1073 iph4->hdr_checksum = 0; 1074 iph4->hdr_checksum = rte_ipv4_cksum(iph4); 1075 } 1076 1077 return 0; 1078 } 1079 1080 #endif /* !RTE_EXEC_ENV_WINDOWS */ 1081