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