1474f1202SAnoob Joseph /* SPDX-License-Identifier: BSD-3-Clause 2474f1202SAnoob Joseph * Copyright(C) 2021 Marvell. 3474f1202SAnoob Joseph */ 4474f1202SAnoob Joseph 5474f1202SAnoob Joseph #include <rte_common.h> 6474f1202SAnoob Joseph #include <rte_cryptodev.h> 7cd928003STejasree Kondoj #include <rte_esp.h> 8474f1202SAnoob Joseph #include <rte_ip.h> 9474f1202SAnoob Joseph #include <rte_security.h> 1083243502SArchana Muniganti #include <rte_tcp.h> 11c8234341STejasree Kondoj #include <rte_udp.h> 12474f1202SAnoob Joseph 13474f1202SAnoob Joseph #include "test.h" 14474f1202SAnoob Joseph #include "test_cryptodev_security_ipsec.h" 15474f1202SAnoob Joseph 16cd928003STejasree Kondoj #define IV_LEN_MAX 16 17cd928003STejasree Kondoj 186622d9c9SAnoob Joseph extern struct ipsec_test_data pkt_aes_256_gcm; 196622d9c9SAnoob Joseph 20474f1202SAnoob Joseph int 21474f1202SAnoob Joseph test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform, 22474f1202SAnoob Joseph const struct rte_security_capability *sec_cap, 23474f1202SAnoob Joseph bool silent) 24474f1202SAnoob Joseph { 25474f1202SAnoob Joseph /* Verify security capabilities */ 26474f1202SAnoob Joseph 27474f1202SAnoob Joseph if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) { 28474f1202SAnoob Joseph if (!silent) 29474f1202SAnoob Joseph RTE_LOG(INFO, USER1, "ESN is not supported\n"); 30474f1202SAnoob Joseph return -ENOTSUP; 31474f1202SAnoob Joseph } 32474f1202SAnoob Joseph 33474f1202SAnoob Joseph if (ipsec_xform->options.udp_encap == 1 && 34474f1202SAnoob Joseph sec_cap->ipsec.options.udp_encap == 0) { 35474f1202SAnoob Joseph if (!silent) 36474f1202SAnoob Joseph RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n"); 37474f1202SAnoob Joseph return -ENOTSUP; 38474f1202SAnoob Joseph } 39474f1202SAnoob Joseph 409ec50a52STejasree Kondoj if (ipsec_xform->options.udp_ports_verify == 1 && 419ec50a52STejasree Kondoj sec_cap->ipsec.options.udp_ports_verify == 0) { 429ec50a52STejasree Kondoj if (!silent) 439ec50a52STejasree Kondoj RTE_LOG(INFO, USER1, "UDP encapsulation ports " 449ec50a52STejasree Kondoj "verification is not supported\n"); 459ec50a52STejasree Kondoj return -ENOTSUP; 469ec50a52STejasree Kondoj } 479ec50a52STejasree Kondoj 48474f1202SAnoob Joseph if (ipsec_xform->options.copy_dscp == 1 && 49474f1202SAnoob Joseph sec_cap->ipsec.options.copy_dscp == 0) { 50474f1202SAnoob Joseph if (!silent) 51474f1202SAnoob Joseph RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n"); 52474f1202SAnoob Joseph return -ENOTSUP; 53474f1202SAnoob Joseph } 54474f1202SAnoob Joseph 55474f1202SAnoob Joseph if (ipsec_xform->options.copy_flabel == 1 && 56474f1202SAnoob Joseph sec_cap->ipsec.options.copy_flabel == 0) { 57474f1202SAnoob Joseph if (!silent) 58474f1202SAnoob Joseph RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n"); 59474f1202SAnoob Joseph return -ENOTSUP; 60474f1202SAnoob Joseph } 61474f1202SAnoob Joseph 62474f1202SAnoob Joseph if (ipsec_xform->options.copy_df == 1 && 63474f1202SAnoob Joseph sec_cap->ipsec.options.copy_df == 0) { 64474f1202SAnoob Joseph if (!silent) 65474f1202SAnoob Joseph RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n"); 66474f1202SAnoob Joseph return -ENOTSUP; 67474f1202SAnoob Joseph } 68474f1202SAnoob Joseph 69474f1202SAnoob Joseph if (ipsec_xform->options.dec_ttl == 1 && 70474f1202SAnoob Joseph sec_cap->ipsec.options.dec_ttl == 0) { 71474f1202SAnoob Joseph if (!silent) 72474f1202SAnoob Joseph RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n"); 73474f1202SAnoob Joseph return -ENOTSUP; 74474f1202SAnoob Joseph } 75474f1202SAnoob Joseph 76474f1202SAnoob Joseph if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) { 77474f1202SAnoob Joseph if (!silent) 78474f1202SAnoob Joseph RTE_LOG(INFO, USER1, "ECN is not supported\n"); 79474f1202SAnoob Joseph return -ENOTSUP; 80474f1202SAnoob Joseph } 81474f1202SAnoob Joseph 82474f1202SAnoob Joseph if (ipsec_xform->options.stats == 1 && 83474f1202SAnoob Joseph sec_cap->ipsec.options.stats == 0) { 84474f1202SAnoob Joseph if (!silent) 85474f1202SAnoob Joseph RTE_LOG(INFO, USER1, "Stats is not supported\n"); 86474f1202SAnoob Joseph return -ENOTSUP; 87474f1202SAnoob Joseph } 88474f1202SAnoob Joseph 890532f50cSAnoob Joseph if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) && 900532f50cSAnoob Joseph (ipsec_xform->options.iv_gen_disable == 1) && 910532f50cSAnoob Joseph (sec_cap->ipsec.options.iv_gen_disable != 1)) { 920532f50cSAnoob Joseph if (!silent) 930532f50cSAnoob Joseph RTE_LOG(INFO, USER1, 940532f50cSAnoob Joseph "Application provided IV is not supported\n"); 950532f50cSAnoob Joseph return -ENOTSUP; 960532f50cSAnoob Joseph } 970532f50cSAnoob Joseph 98270470eeSTejasree Kondoj if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 99270470eeSTejasree Kondoj (ipsec_xform->options.tunnel_hdr_verify > 100270470eeSTejasree Kondoj sec_cap->ipsec.options.tunnel_hdr_verify)) { 101270470eeSTejasree Kondoj if (!silent) 102270470eeSTejasree Kondoj RTE_LOG(INFO, USER1, 103270470eeSTejasree Kondoj "Tunnel header verify is not supported\n"); 104270470eeSTejasree Kondoj return -ENOTSUP; 105270470eeSTejasree Kondoj } 106270470eeSTejasree Kondoj 10783243502SArchana Muniganti if (ipsec_xform->options.ip_csum_enable == 1 && 10883243502SArchana Muniganti sec_cap->ipsec.options.ip_csum_enable == 0) { 10983243502SArchana Muniganti if (!silent) 11083243502SArchana Muniganti RTE_LOG(INFO, USER1, 11183243502SArchana Muniganti "Inner IP checksum is not supported\n"); 11283243502SArchana Muniganti return -ENOTSUP; 11383243502SArchana Muniganti } 11483243502SArchana Muniganti 11583243502SArchana Muniganti if (ipsec_xform->options.l4_csum_enable == 1 && 11683243502SArchana Muniganti sec_cap->ipsec.options.l4_csum_enable == 0) { 11783243502SArchana Muniganti if (!silent) 11883243502SArchana Muniganti RTE_LOG(INFO, USER1, 11983243502SArchana Muniganti "Inner L4 checksum is not supported\n"); 12083243502SArchana Muniganti return -ENOTSUP; 12183243502SArchana Muniganti } 12283243502SArchana Muniganti 123474f1202SAnoob Joseph return 0; 124474f1202SAnoob Joseph } 125474f1202SAnoob Joseph 126474f1202SAnoob Joseph int 127474f1202SAnoob Joseph test_ipsec_crypto_caps_aead_verify( 128474f1202SAnoob Joseph const struct rte_security_capability *sec_cap, 129474f1202SAnoob Joseph struct rte_crypto_sym_xform *aead) 130474f1202SAnoob Joseph { 131474f1202SAnoob Joseph const struct rte_cryptodev_symmetric_capability *sym_cap; 132474f1202SAnoob Joseph const struct rte_cryptodev_capabilities *crypto_cap; 133474f1202SAnoob Joseph int j = 0; 134474f1202SAnoob Joseph 135474f1202SAnoob Joseph while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op != 136474f1202SAnoob Joseph RTE_CRYPTO_OP_TYPE_UNDEFINED) { 137474f1202SAnoob Joseph if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC && 138474f1202SAnoob Joseph crypto_cap->sym.xform_type == aead->type && 139474f1202SAnoob Joseph crypto_cap->sym.aead.algo == aead->aead.algo) { 140474f1202SAnoob Joseph sym_cap = &crypto_cap->sym; 141474f1202SAnoob Joseph if (rte_cryptodev_sym_capability_check_aead(sym_cap, 142474f1202SAnoob Joseph aead->aead.key.length, 143474f1202SAnoob Joseph aead->aead.digest_length, 144474f1202SAnoob Joseph aead->aead.aad_length, 145474f1202SAnoob Joseph aead->aead.iv.length) == 0) 146474f1202SAnoob Joseph return 0; 147474f1202SAnoob Joseph } 148474f1202SAnoob Joseph } 149474f1202SAnoob Joseph 150474f1202SAnoob Joseph return -ENOTSUP; 151474f1202SAnoob Joseph } 152474f1202SAnoob Joseph 153474f1202SAnoob Joseph void 154474f1202SAnoob Joseph test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out, 155474f1202SAnoob Joseph struct ipsec_test_data *td_in) 156474f1202SAnoob Joseph { 157474f1202SAnoob Joseph memcpy(td_in, td_out, sizeof(*td_in)); 158474f1202SAnoob Joseph 159474f1202SAnoob Joseph /* Populate output text of td_in with input text of td_out */ 160474f1202SAnoob Joseph memcpy(td_in->output_text.data, td_out->input_text.data, 161474f1202SAnoob Joseph td_out->input_text.len); 162474f1202SAnoob Joseph td_in->output_text.len = td_out->input_text.len; 163474f1202SAnoob Joseph 164474f1202SAnoob Joseph /* Populate input text of td_in with output text of td_out */ 165474f1202SAnoob Joseph memcpy(td_in->input_text.data, td_out->output_text.data, 166474f1202SAnoob Joseph td_out->output_text.len); 167474f1202SAnoob Joseph td_in->input_text.len = td_out->output_text.len; 168474f1202SAnoob Joseph 169474f1202SAnoob Joseph td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; 170474f1202SAnoob Joseph 171474f1202SAnoob Joseph if (td_in->aead) { 172474f1202SAnoob Joseph td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT; 173474f1202SAnoob Joseph } else { 174474f1202SAnoob Joseph td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; 175474f1202SAnoob Joseph td_in->xform.chain.cipher.cipher.op = 176474f1202SAnoob Joseph RTE_CRYPTO_CIPHER_OP_DECRYPT; 177474f1202SAnoob Joseph } 178474f1202SAnoob Joseph } 179474f1202SAnoob Joseph 18083243502SArchana Muniganti static bool 18183243502SArchana Muniganti is_ipv4(void *ip) 18283243502SArchana Muniganti { 18383243502SArchana Muniganti struct rte_ipv4_hdr *ipv4 = ip; 18483243502SArchana Muniganti uint8_t ip_ver; 18583243502SArchana Muniganti 18683243502SArchana Muniganti ip_ver = (ipv4->version_ihl & 0xf0) >> RTE_IPV4_IHL_MULTIPLIER; 18783243502SArchana Muniganti if (ip_ver == IPVERSION) 18883243502SArchana Muniganti return true; 18983243502SArchana Muniganti else 19083243502SArchana Muniganti return false; 19183243502SArchana Muniganti } 19283243502SArchana Muniganti 19383243502SArchana Muniganti static void 19483243502SArchana Muniganti test_ipsec_csum_init(void *ip, bool l3, bool l4) 19583243502SArchana Muniganti { 19683243502SArchana Muniganti struct rte_ipv4_hdr *ipv4; 19783243502SArchana Muniganti struct rte_tcp_hdr *tcp; 19883243502SArchana Muniganti struct rte_udp_hdr *udp; 19983243502SArchana Muniganti uint8_t next_proto; 20083243502SArchana Muniganti uint8_t size; 20183243502SArchana Muniganti 20283243502SArchana Muniganti if (is_ipv4(ip)) { 20383243502SArchana Muniganti ipv4 = ip; 20483243502SArchana Muniganti size = sizeof(struct rte_ipv4_hdr); 20583243502SArchana Muniganti next_proto = ipv4->next_proto_id; 20683243502SArchana Muniganti 20783243502SArchana Muniganti if (l3) 20883243502SArchana Muniganti ipv4->hdr_checksum = 0; 20983243502SArchana Muniganti } else { 21083243502SArchana Muniganti size = sizeof(struct rte_ipv6_hdr); 21183243502SArchana Muniganti next_proto = ((struct rte_ipv6_hdr *)ip)->proto; 21283243502SArchana Muniganti } 21383243502SArchana Muniganti 21483243502SArchana Muniganti if (l4) { 21583243502SArchana Muniganti switch (next_proto) { 21683243502SArchana Muniganti case IPPROTO_TCP: 21783243502SArchana Muniganti tcp = (struct rte_tcp_hdr *)RTE_PTR_ADD(ip, size); 21883243502SArchana Muniganti tcp->cksum = 0; 21983243502SArchana Muniganti break; 22083243502SArchana Muniganti case IPPROTO_UDP: 22183243502SArchana Muniganti udp = (struct rte_udp_hdr *)RTE_PTR_ADD(ip, size); 22283243502SArchana Muniganti udp->dgram_cksum = 0; 22383243502SArchana Muniganti break; 22483243502SArchana Muniganti default: 22583243502SArchana Muniganti return; 22683243502SArchana Muniganti } 22783243502SArchana Muniganti } 22883243502SArchana Muniganti } 22983243502SArchana Muniganti 2306622d9c9SAnoob Joseph void 2316622d9c9SAnoob Joseph test_ipsec_td_prepare(const struct crypto_param *param1, 2326622d9c9SAnoob Joseph const struct crypto_param *param2, 2336622d9c9SAnoob Joseph const struct ipsec_test_flags *flags, 2346622d9c9SAnoob Joseph struct ipsec_test_data *td_array, 2356622d9c9SAnoob Joseph int nb_td) 2366622d9c9SAnoob Joseph 2376622d9c9SAnoob Joseph { 2386622d9c9SAnoob Joseph struct ipsec_test_data *td; 2396622d9c9SAnoob Joseph int i; 2406622d9c9SAnoob Joseph 2416622d9c9SAnoob Joseph memset(td_array, 0, nb_td * sizeof(*td)); 2426622d9c9SAnoob Joseph 2436622d9c9SAnoob Joseph for (i = 0; i < nb_td; i++) { 2446622d9c9SAnoob Joseph td = &td_array[i]; 2456622d9c9SAnoob Joseph /* Copy template for packet & key fields */ 2466622d9c9SAnoob Joseph memcpy(td, &pkt_aes_256_gcm, sizeof(*td)); 2476622d9c9SAnoob Joseph 2486622d9c9SAnoob Joseph /* Override fields based on param */ 2496622d9c9SAnoob Joseph 2506622d9c9SAnoob Joseph if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) 2516622d9c9SAnoob Joseph td->aead = true; 2526622d9c9SAnoob Joseph else 2536622d9c9SAnoob Joseph td->aead = false; 2546622d9c9SAnoob Joseph 2556622d9c9SAnoob Joseph td->xform.aead.aead.algo = param1->alg.aead; 2566622d9c9SAnoob Joseph td->xform.aead.aead.key.length = param1->key_length; 2570532f50cSAnoob Joseph 2580532f50cSAnoob Joseph if (flags->iv_gen) 2590532f50cSAnoob Joseph td->ipsec_xform.options.iv_gen_disable = 0; 2604aa52f21SAnoob Joseph 2614aa52f21SAnoob Joseph if (flags->sa_expiry_pkts_soft) 2624aa52f21SAnoob Joseph td->ipsec_xform.life.packets_soft_limit = 2634aa52f21SAnoob Joseph IPSEC_TEST_PACKETS_MAX - 1; 26483243502SArchana Muniganti 26583243502SArchana Muniganti if (flags->ip_csum) { 26683243502SArchana Muniganti td->ipsec_xform.options.ip_csum_enable = 1; 26783243502SArchana Muniganti test_ipsec_csum_init(&td->input_text.data, true, false); 26883243502SArchana Muniganti } 26983243502SArchana Muniganti 27083243502SArchana Muniganti if (flags->l4_csum) { 27183243502SArchana Muniganti td->ipsec_xform.options.l4_csum_enable = 1; 27283243502SArchana Muniganti test_ipsec_csum_init(&td->input_text.data, false, true); 27383243502SArchana Muniganti } 27483243502SArchana Muniganti 2756622d9c9SAnoob Joseph } 2766622d9c9SAnoob Joseph 2776622d9c9SAnoob Joseph RTE_SET_USED(param2); 2786622d9c9SAnoob Joseph } 2796622d9c9SAnoob Joseph 2806622d9c9SAnoob Joseph void 2816622d9c9SAnoob Joseph test_ipsec_td_update(struct ipsec_test_data td_inb[], 2826622d9c9SAnoob Joseph const struct ipsec_test_data td_outb[], 2836622d9c9SAnoob Joseph int nb_td, 2846622d9c9SAnoob Joseph const struct ipsec_test_flags *flags) 2856622d9c9SAnoob Joseph { 2866622d9c9SAnoob Joseph int i; 2876622d9c9SAnoob Joseph 2886622d9c9SAnoob Joseph for (i = 0; i < nb_td; i++) { 2896622d9c9SAnoob Joseph memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data, 2906622d9c9SAnoob Joseph td_outb[i].input_text.len); 2916622d9c9SAnoob Joseph td_inb[i].output_text.len = td_outb->input_text.len; 2926622d9c9SAnoob Joseph 2930f453190STejasree Kondoj if (flags->icv_corrupt) { 2940f453190STejasree Kondoj int icv_pos = td_inb[i].input_text.len - 4; 2950f453190STejasree Kondoj td_inb[i].input_text.data[icv_pos] += 1; 2960f453190STejasree Kondoj } 297c8234341STejasree Kondoj 2986978f51eSAnoob Joseph if (flags->sa_expiry_pkts_hard) 2996978f51eSAnoob Joseph td_inb[i].ipsec_xform.life.packets_hard_limit = 3006978f51eSAnoob Joseph IPSEC_TEST_PACKETS_MAX - 1; 3016978f51eSAnoob Joseph 302c8234341STejasree Kondoj if (flags->udp_encap) 303c8234341STejasree Kondoj td_inb[i].ipsec_xform.options.udp_encap = 1; 3040532f50cSAnoob Joseph 3059ec50a52STejasree Kondoj if (flags->udp_ports_verify) 3069ec50a52STejasree Kondoj td_inb[i].ipsec_xform.options.udp_ports_verify = 1; 3079ec50a52STejasree Kondoj 308270470eeSTejasree Kondoj td_inb[i].ipsec_xform.options.tunnel_hdr_verify = 309270470eeSTejasree Kondoj flags->tunnel_hdr_verify; 310270470eeSTejasree Kondoj 31183243502SArchana Muniganti if (flags->ip_csum) 31283243502SArchana Muniganti td_inb[i].ipsec_xform.options.ip_csum_enable = 1; 31383243502SArchana Muniganti 31483243502SArchana Muniganti if (flags->l4_csum) 31583243502SArchana Muniganti td_inb[i].ipsec_xform.options.l4_csum_enable = 1; 31683243502SArchana Muniganti 3170532f50cSAnoob Joseph /* Clear outbound specific flags */ 3180532f50cSAnoob Joseph td_inb[i].ipsec_xform.options.iv_gen_disable = 0; 3190f453190STejasree Kondoj } 3206622d9c9SAnoob Joseph } 3216622d9c9SAnoob Joseph 3226622d9c9SAnoob Joseph void 3236622d9c9SAnoob Joseph test_ipsec_display_alg(const struct crypto_param *param1, 3246622d9c9SAnoob Joseph const struct crypto_param *param2) 3256622d9c9SAnoob Joseph { 3266622d9c9SAnoob Joseph if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) 3276622d9c9SAnoob Joseph printf("\t%s [%d]\n", 3286622d9c9SAnoob Joseph rte_crypto_aead_algorithm_strings[param1->alg.aead], 3296622d9c9SAnoob Joseph param1->key_length); 3306622d9c9SAnoob Joseph 3316622d9c9SAnoob Joseph RTE_SET_USED(param2); 3326622d9c9SAnoob Joseph } 3336622d9c9SAnoob Joseph 334474f1202SAnoob Joseph static int 335474f1202SAnoob Joseph test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td) 336474f1202SAnoob Joseph { 337474f1202SAnoob Joseph int len = 0; 338474f1202SAnoob Joseph 339474f1202SAnoob Joseph if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 340474f1202SAnoob Joseph if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) { 341474f1202SAnoob Joseph if (td->ipsec_xform.tunnel.type == 342474f1202SAnoob Joseph RTE_SECURITY_IPSEC_TUNNEL_IPV4) 343474f1202SAnoob Joseph len += sizeof(struct rte_ipv4_hdr); 344474f1202SAnoob Joseph else 345474f1202SAnoob Joseph len += sizeof(struct rte_ipv6_hdr); 346474f1202SAnoob Joseph } 347474f1202SAnoob Joseph } 348474f1202SAnoob Joseph 349474f1202SAnoob Joseph return len; 350474f1202SAnoob Joseph } 351474f1202SAnoob Joseph 352474f1202SAnoob Joseph static int 353cd928003STejasree Kondoj test_ipsec_iv_verify_push(struct rte_mbuf *m, const struct ipsec_test_data *td) 354cd928003STejasree Kondoj { 355cd928003STejasree Kondoj static uint8_t iv_queue[IV_LEN_MAX * IPSEC_TEST_PACKETS_MAX]; 356cd928003STejasree Kondoj uint8_t *iv_tmp, *output_text = rte_pktmbuf_mtod(m, uint8_t *); 357cd928003STejasree Kondoj int i, iv_pos, iv_len; 358cd928003STejasree Kondoj static int index; 359cd928003STejasree Kondoj 360cd928003STejasree Kondoj if (td->aead) 361cd928003STejasree Kondoj iv_len = td->xform.aead.aead.iv.length - td->salt.len; 362cd928003STejasree Kondoj else 363cd928003STejasree Kondoj iv_len = td->xform.chain.cipher.cipher.iv.length; 364cd928003STejasree Kondoj 365cd928003STejasree Kondoj iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr); 366cd928003STejasree Kondoj output_text += iv_pos; 367cd928003STejasree Kondoj 368cd928003STejasree Kondoj TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported"); 369cd928003STejasree Kondoj 370cd928003STejasree Kondoj /* Compare against previous values */ 371cd928003STejasree Kondoj for (i = 0; i < index; i++) { 372cd928003STejasree Kondoj iv_tmp = &iv_queue[i * IV_LEN_MAX]; 373cd928003STejasree Kondoj 374cd928003STejasree Kondoj if (memcmp(output_text, iv_tmp, iv_len) == 0) { 375cd928003STejasree Kondoj printf("IV repeated"); 376cd928003STejasree Kondoj return TEST_FAILED; 377cd928003STejasree Kondoj } 378cd928003STejasree Kondoj } 379cd928003STejasree Kondoj 380cd928003STejasree Kondoj /* Save IV for future comparisons */ 381cd928003STejasree Kondoj 382cd928003STejasree Kondoj iv_tmp = &iv_queue[index * IV_LEN_MAX]; 383cd928003STejasree Kondoj memcpy(iv_tmp, output_text, iv_len); 384cd928003STejasree Kondoj index++; 385cd928003STejasree Kondoj 386cd928003STejasree Kondoj if (index == IPSEC_TEST_PACKETS_MAX) 387cd928003STejasree Kondoj index = 0; 388cd928003STejasree Kondoj 389cd928003STejasree Kondoj return TEST_SUCCESS; 390cd928003STejasree Kondoj } 391cd928003STejasree Kondoj 392cd928003STejasree Kondoj static int 39383243502SArchana Muniganti test_ipsec_l3_csum_verify(struct rte_mbuf *m) 39483243502SArchana Muniganti { 39583243502SArchana Muniganti uint16_t actual_cksum, expected_cksum; 39683243502SArchana Muniganti struct rte_ipv4_hdr *ip; 39783243502SArchana Muniganti 39883243502SArchana Muniganti ip = rte_pktmbuf_mtod(m, struct rte_ipv4_hdr *); 39983243502SArchana Muniganti 40083243502SArchana Muniganti if (!is_ipv4((void *)ip)) 40183243502SArchana Muniganti return TEST_SKIPPED; 40283243502SArchana Muniganti 40383243502SArchana Muniganti actual_cksum = ip->hdr_checksum; 40483243502SArchana Muniganti 40583243502SArchana Muniganti ip->hdr_checksum = 0; 40683243502SArchana Muniganti 40783243502SArchana Muniganti expected_cksum = rte_ipv4_cksum(ip); 40883243502SArchana Muniganti 40983243502SArchana Muniganti if (actual_cksum != expected_cksum) 41083243502SArchana Muniganti return TEST_FAILED; 41183243502SArchana Muniganti 41283243502SArchana Muniganti return TEST_SUCCESS; 41383243502SArchana Muniganti } 41483243502SArchana Muniganti 41583243502SArchana Muniganti static int 41683243502SArchana Muniganti test_ipsec_l4_csum_verify(struct rte_mbuf *m) 41783243502SArchana Muniganti { 41883243502SArchana Muniganti uint16_t actual_cksum = 0, expected_cksum = 0; 41983243502SArchana Muniganti struct rte_ipv4_hdr *ipv4; 42083243502SArchana Muniganti struct rte_ipv6_hdr *ipv6; 42183243502SArchana Muniganti struct rte_tcp_hdr *tcp; 42283243502SArchana Muniganti struct rte_udp_hdr *udp; 42383243502SArchana Muniganti void *ip, *l4; 42483243502SArchana Muniganti 42583243502SArchana Muniganti ip = rte_pktmbuf_mtod(m, void *); 42683243502SArchana Muniganti 42783243502SArchana Muniganti if (is_ipv4(ip)) { 42883243502SArchana Muniganti ipv4 = ip; 42983243502SArchana Muniganti l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr)); 43083243502SArchana Muniganti 43183243502SArchana Muniganti switch (ipv4->next_proto_id) { 43283243502SArchana Muniganti case IPPROTO_TCP: 43383243502SArchana Muniganti tcp = (struct rte_tcp_hdr *)l4; 43483243502SArchana Muniganti actual_cksum = tcp->cksum; 43583243502SArchana Muniganti tcp->cksum = 0; 43683243502SArchana Muniganti expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4); 43783243502SArchana Muniganti break; 43883243502SArchana Muniganti case IPPROTO_UDP: 43983243502SArchana Muniganti udp = (struct rte_udp_hdr *)l4; 44083243502SArchana Muniganti actual_cksum = udp->dgram_cksum; 44183243502SArchana Muniganti udp->dgram_cksum = 0; 44283243502SArchana Muniganti expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4); 44383243502SArchana Muniganti break; 44483243502SArchana Muniganti default: 44583243502SArchana Muniganti break; 44683243502SArchana Muniganti } 44783243502SArchana Muniganti } else { 44883243502SArchana Muniganti ipv6 = ip; 44983243502SArchana Muniganti l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr)); 45083243502SArchana Muniganti 45183243502SArchana Muniganti switch (ipv6->proto) { 45283243502SArchana Muniganti case IPPROTO_TCP: 45383243502SArchana Muniganti tcp = (struct rte_tcp_hdr *)l4; 45483243502SArchana Muniganti actual_cksum = tcp->cksum; 45583243502SArchana Muniganti tcp->cksum = 0; 45683243502SArchana Muniganti expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4); 45783243502SArchana Muniganti break; 45883243502SArchana Muniganti case IPPROTO_UDP: 45983243502SArchana Muniganti udp = (struct rte_udp_hdr *)l4; 46083243502SArchana Muniganti actual_cksum = udp->dgram_cksum; 46183243502SArchana Muniganti udp->dgram_cksum = 0; 46283243502SArchana Muniganti expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4); 46383243502SArchana Muniganti break; 46483243502SArchana Muniganti default: 46583243502SArchana Muniganti break; 46683243502SArchana Muniganti } 46783243502SArchana Muniganti } 46883243502SArchana Muniganti 46983243502SArchana Muniganti if (actual_cksum != expected_cksum) 47083243502SArchana Muniganti return TEST_FAILED; 47183243502SArchana Muniganti 47283243502SArchana Muniganti return TEST_SUCCESS; 47383243502SArchana Muniganti } 47483243502SArchana Muniganti 47583243502SArchana Muniganti static int 476474f1202SAnoob Joseph test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td, 4776622d9c9SAnoob Joseph bool silent, const struct ipsec_test_flags *flags) 478474f1202SAnoob Joseph { 479474f1202SAnoob Joseph uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 480474f1202SAnoob Joseph uint32_t skip, len = rte_pktmbuf_pkt_len(m); 48183243502SArchana Muniganti int ret; 482474f1202SAnoob Joseph 4836978f51eSAnoob Joseph /* For tests with status as error for test success, skip verification */ 4846978f51eSAnoob Joseph if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && 4856978f51eSAnoob Joseph (flags->icv_corrupt || 486270470eeSTejasree Kondoj flags->sa_expiry_pkts_hard || 487270470eeSTejasree Kondoj flags->tunnel_hdr_verify)) 4880f453190STejasree Kondoj return TEST_SUCCESS; 4890f453190STejasree Kondoj 490c8234341STejasree Kondoj if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS && 491c8234341STejasree Kondoj flags->udp_encap) { 492c8234341STejasree Kondoj const struct rte_ipv4_hdr *iph4; 493c8234341STejasree Kondoj const struct rte_ipv6_hdr *iph6; 494c8234341STejasree Kondoj 495c8234341STejasree Kondoj if (td->ipsec_xform.tunnel.type == 496c8234341STejasree Kondoj RTE_SECURITY_IPSEC_TUNNEL_IPV4) { 497c8234341STejasree Kondoj iph4 = (const struct rte_ipv4_hdr *)output_text; 498c8234341STejasree Kondoj if (iph4->next_proto_id != IPPROTO_UDP) { 499c8234341STejasree Kondoj printf("UDP header is not found\n"); 500c8234341STejasree Kondoj return TEST_FAILED; 501c8234341STejasree Kondoj } 502c8234341STejasree Kondoj } else { 503c8234341STejasree Kondoj iph6 = (const struct rte_ipv6_hdr *)output_text; 504c8234341STejasree Kondoj if (iph6->proto != IPPROTO_UDP) { 505c8234341STejasree Kondoj printf("UDP header is not found\n"); 506c8234341STejasree Kondoj return TEST_FAILED; 507c8234341STejasree Kondoj } 508c8234341STejasree Kondoj } 509c8234341STejasree Kondoj 510c8234341STejasree Kondoj len -= sizeof(struct rte_udp_hdr); 511c8234341STejasree Kondoj output_text += sizeof(struct rte_udp_hdr); 512c8234341STejasree Kondoj } 513c8234341STejasree Kondoj 514474f1202SAnoob Joseph if (len != td->output_text.len) { 515474f1202SAnoob Joseph printf("Output length (%d) not matching with expected (%d)\n", 516474f1202SAnoob Joseph len, td->output_text.len); 517474f1202SAnoob Joseph return TEST_FAILED; 518474f1202SAnoob Joseph } 519474f1202SAnoob Joseph 520474f1202SAnoob Joseph skip = test_ipsec_tunnel_hdr_len_get(td); 521474f1202SAnoob Joseph 522474f1202SAnoob Joseph len -= skip; 523474f1202SAnoob Joseph output_text += skip; 524474f1202SAnoob Joseph 52583243502SArchana Muniganti if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 52683243502SArchana Muniganti flags->ip_csum) { 527*daa02b5cSOlivier Matz if (m->ol_flags & RTE_MBUF_F_RX_IP_CKSUM_GOOD) 52883243502SArchana Muniganti ret = test_ipsec_l3_csum_verify(m); 52983243502SArchana Muniganti else 53083243502SArchana Muniganti ret = TEST_FAILED; 53183243502SArchana Muniganti 53283243502SArchana Muniganti if (ret == TEST_FAILED) 53383243502SArchana Muniganti printf("Inner IP checksum test failed\n"); 53483243502SArchana Muniganti 53583243502SArchana Muniganti return ret; 53683243502SArchana Muniganti } 53783243502SArchana Muniganti 53883243502SArchana Muniganti if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 53983243502SArchana Muniganti flags->l4_csum) { 540*daa02b5cSOlivier Matz if (m->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD) 54183243502SArchana Muniganti ret = test_ipsec_l4_csum_verify(m); 54283243502SArchana Muniganti else 54383243502SArchana Muniganti ret = TEST_FAILED; 54483243502SArchana Muniganti 54583243502SArchana Muniganti if (ret == TEST_FAILED) 54683243502SArchana Muniganti printf("Inner L4 checksum test failed\n"); 54783243502SArchana Muniganti 54883243502SArchana Muniganti return ret; 54983243502SArchana Muniganti } 55083243502SArchana Muniganti 55183243502SArchana Muniganti 552474f1202SAnoob Joseph if (memcmp(output_text, td->output_text.data + skip, len)) { 553474f1202SAnoob Joseph if (silent) 554474f1202SAnoob Joseph return TEST_FAILED; 555474f1202SAnoob Joseph 556474f1202SAnoob Joseph printf("TestCase %s line %d: %s\n", __func__, __LINE__, 557474f1202SAnoob Joseph "output text not as expected\n"); 558474f1202SAnoob Joseph 559474f1202SAnoob Joseph rte_hexdump(stdout, "expected", td->output_text.data + skip, 560474f1202SAnoob Joseph len); 561474f1202SAnoob Joseph rte_hexdump(stdout, "actual", output_text, len); 562474f1202SAnoob Joseph return TEST_FAILED; 563474f1202SAnoob Joseph } 564474f1202SAnoob Joseph 5656622d9c9SAnoob Joseph return TEST_SUCCESS; 5666622d9c9SAnoob Joseph } 5676622d9c9SAnoob Joseph 5686622d9c9SAnoob Joseph static int 5696622d9c9SAnoob Joseph test_ipsec_res_d_prepare(struct rte_mbuf *m, const struct ipsec_test_data *td, 5706622d9c9SAnoob Joseph struct ipsec_test_data *res_d) 5716622d9c9SAnoob Joseph { 5726622d9c9SAnoob Joseph uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *); 5736622d9c9SAnoob Joseph uint32_t len = rte_pktmbuf_pkt_len(m); 5746622d9c9SAnoob Joseph 5756622d9c9SAnoob Joseph memcpy(res_d, td, sizeof(*res_d)); 5766622d9c9SAnoob Joseph memcpy(res_d->input_text.data, output_text, len); 5776622d9c9SAnoob Joseph res_d->input_text.len = len; 5786622d9c9SAnoob Joseph 5796622d9c9SAnoob Joseph res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS; 5806622d9c9SAnoob Joseph if (res_d->aead) { 5816622d9c9SAnoob Joseph res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT; 5826622d9c9SAnoob Joseph } else { 5836622d9c9SAnoob Joseph printf("Only AEAD supported\n"); 5846622d9c9SAnoob Joseph return TEST_SKIPPED; 5856622d9c9SAnoob Joseph } 5866622d9c9SAnoob Joseph 587474f1202SAnoob Joseph return TEST_SUCCESS; 588474f1202SAnoob Joseph } 589474f1202SAnoob Joseph 590474f1202SAnoob Joseph int 591474f1202SAnoob Joseph test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td, 5926622d9c9SAnoob Joseph struct ipsec_test_data *res_d, bool silent, 5936622d9c9SAnoob Joseph const struct ipsec_test_flags *flags) 594474f1202SAnoob Joseph { 595cd928003STejasree Kondoj int ret; 596cd928003STejasree Kondoj 597cd928003STejasree Kondoj if (flags->iv_gen && 598cd928003STejasree Kondoj td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) { 599cd928003STejasree Kondoj ret = test_ipsec_iv_verify_push(m, td); 600cd928003STejasree Kondoj if (ret != TEST_SUCCESS) 601cd928003STejasree Kondoj return ret; 602cd928003STejasree Kondoj } 603cd928003STejasree Kondoj 604474f1202SAnoob Joseph /* 605474f1202SAnoob Joseph * In case of known vector tests & all inbound tests, res_d provided 606474f1202SAnoob Joseph * would be NULL and output data need to be validated against expected. 607474f1202SAnoob Joseph * For inbound, output_text would be plain packet and for outbound 608474f1202SAnoob Joseph * output_text would IPsec packet. Validate by comparing against 609474f1202SAnoob Joseph * known vectors. 6106622d9c9SAnoob Joseph * 6116622d9c9SAnoob Joseph * In case of combined mode tests, the output_text from outbound 6126622d9c9SAnoob Joseph * operation (ie, IPsec packet) would need to be inbound processed to 6136622d9c9SAnoob Joseph * obtain the plain text. Copy output_text to result data, 'res_d', so 6146622d9c9SAnoob Joseph * that inbound processing can be done. 615474f1202SAnoob Joseph */ 6166622d9c9SAnoob Joseph 6176622d9c9SAnoob Joseph if (res_d == NULL) 6186622d9c9SAnoob Joseph return test_ipsec_td_verify(m, td, silent, flags); 6196622d9c9SAnoob Joseph else 6206622d9c9SAnoob Joseph return test_ipsec_res_d_prepare(m, td, res_d); 621474f1202SAnoob Joseph } 622474f1202SAnoob Joseph 623474f1202SAnoob Joseph int 624474f1202SAnoob Joseph test_ipsec_status_check(struct rte_crypto_op *op, 6256622d9c9SAnoob Joseph const struct ipsec_test_flags *flags, 6264aa52f21SAnoob Joseph enum rte_security_ipsec_sa_direction dir, 6274aa52f21SAnoob Joseph int pkt_num) 628474f1202SAnoob Joseph { 629474f1202SAnoob Joseph int ret = TEST_SUCCESS; 630474f1202SAnoob Joseph 6316978f51eSAnoob Joseph if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && 6326978f51eSAnoob Joseph flags->sa_expiry_pkts_hard && 6336978f51eSAnoob Joseph pkt_num == IPSEC_TEST_PACKETS_MAX) { 6346978f51eSAnoob Joseph if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 6356978f51eSAnoob Joseph printf("SA hard expiry (pkts) test failed\n"); 6366978f51eSAnoob Joseph return TEST_FAILED; 6376978f51eSAnoob Joseph } else { 6386978f51eSAnoob Joseph return TEST_SUCCESS; 6396978f51eSAnoob Joseph } 6406978f51eSAnoob Joseph } 6416978f51eSAnoob Joseph 642270470eeSTejasree Kondoj if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) && 643270470eeSTejasree Kondoj flags->tunnel_hdr_verify) { 644270470eeSTejasree Kondoj if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 645270470eeSTejasree Kondoj printf("Tunnel header verify test case failed\n"); 646270470eeSTejasree Kondoj return TEST_FAILED; 647270470eeSTejasree Kondoj } else { 648270470eeSTejasree Kondoj return TEST_SUCCESS; 649270470eeSTejasree Kondoj } 650270470eeSTejasree Kondoj } 651270470eeSTejasree Kondoj 6520f453190STejasree Kondoj if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) { 6530f453190STejasree Kondoj if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) { 6540f453190STejasree Kondoj printf("ICV corruption test case failed\n"); 6550f453190STejasree Kondoj ret = TEST_FAILED; 6560f453190STejasree Kondoj } 6570f453190STejasree Kondoj } else { 658474f1202SAnoob Joseph if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) { 6594aa52f21SAnoob Joseph printf("Security op processing failed [pkt_num: %d]\n", 6604aa52f21SAnoob Joseph pkt_num); 6614aa52f21SAnoob Joseph ret = TEST_FAILED; 6624aa52f21SAnoob Joseph } 6634aa52f21SAnoob Joseph } 6644aa52f21SAnoob Joseph 6654aa52f21SAnoob Joseph if (flags->sa_expiry_pkts_soft && pkt_num == IPSEC_TEST_PACKETS_MAX) { 6664aa52f21SAnoob Joseph if (!(op->aux_flags & 6674aa52f21SAnoob Joseph RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) { 6684aa52f21SAnoob Joseph printf("SA soft expiry (pkts) test failed\n"); 669474f1202SAnoob Joseph ret = TEST_FAILED; 670474f1202SAnoob Joseph } 6710f453190STejasree Kondoj } 672474f1202SAnoob Joseph 673474f1202SAnoob Joseph return ret; 674474f1202SAnoob Joseph } 675