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