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