bpf: allow self-xor operation
[dpdk.git] / app / test / test_cryptodev_security_ipsec.c
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 extern struct ipsec_test_data pkt_aes_256_gcm;
19
20 int
21 test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
22                            const struct rte_security_capability *sec_cap,
23                            bool silent)
24 {
25         /* Verify security capabilities */
26
27         if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) {
28                 if (!silent)
29                         RTE_LOG(INFO, USER1, "ESN is not supported\n");
30                 return -ENOTSUP;
31         }
32
33         if (ipsec_xform->options.udp_encap == 1 &&
34             sec_cap->ipsec.options.udp_encap == 0) {
35                 if (!silent)
36                         RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n");
37                 return -ENOTSUP;
38         }
39
40         if (ipsec_xform->options.udp_ports_verify == 1 &&
41             sec_cap->ipsec.options.udp_ports_verify == 0) {
42                 if (!silent)
43                         RTE_LOG(INFO, USER1, "UDP encapsulation ports "
44                                 "verification is not supported\n");
45                 return -ENOTSUP;
46         }
47
48         if (ipsec_xform->options.copy_dscp == 1 &&
49             sec_cap->ipsec.options.copy_dscp == 0) {
50                 if (!silent)
51                         RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n");
52                 return -ENOTSUP;
53         }
54
55         if (ipsec_xform->options.copy_flabel == 1 &&
56             sec_cap->ipsec.options.copy_flabel == 0) {
57                 if (!silent)
58                         RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n");
59                 return -ENOTSUP;
60         }
61
62         if (ipsec_xform->options.copy_df == 1 &&
63             sec_cap->ipsec.options.copy_df == 0) {
64                 if (!silent)
65                         RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n");
66                 return -ENOTSUP;
67         }
68
69         if (ipsec_xform->options.dec_ttl == 1 &&
70             sec_cap->ipsec.options.dec_ttl == 0) {
71                 if (!silent)
72                         RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n");
73                 return -ENOTSUP;
74         }
75
76         if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) {
77                 if (!silent)
78                         RTE_LOG(INFO, USER1, "ECN is not supported\n");
79                 return -ENOTSUP;
80         }
81
82         if (ipsec_xform->options.stats == 1 &&
83             sec_cap->ipsec.options.stats == 0) {
84                 if (!silent)
85                         RTE_LOG(INFO, USER1, "Stats is not supported\n");
86                 return -ENOTSUP;
87         }
88
89         if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) &&
90             (ipsec_xform->options.iv_gen_disable == 1) &&
91             (sec_cap->ipsec.options.iv_gen_disable != 1)) {
92                 if (!silent)
93                         RTE_LOG(INFO, USER1,
94                                 "Application provided IV is not supported\n");
95                 return -ENOTSUP;
96         }
97
98         if ((ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
99             (ipsec_xform->options.tunnel_hdr_verify >
100             sec_cap->ipsec.options.tunnel_hdr_verify)) {
101                 if (!silent)
102                         RTE_LOG(INFO, USER1,
103                                 "Tunnel header verify is not supported\n");
104                 return -ENOTSUP;
105         }
106
107         if (ipsec_xform->options.ip_csum_enable == 1 &&
108             sec_cap->ipsec.options.ip_csum_enable == 0) {
109                 if (!silent)
110                         RTE_LOG(INFO, USER1,
111                                 "Inner IP checksum is not supported\n");
112                 return -ENOTSUP;
113         }
114
115         if (ipsec_xform->options.l4_csum_enable == 1 &&
116             sec_cap->ipsec.options.l4_csum_enable == 0) {
117                 if (!silent)
118                         RTE_LOG(INFO, USER1,
119                                 "Inner L4 checksum is not supported\n");
120                 return -ENOTSUP;
121         }
122
123         return 0;
124 }
125
126 int
127 test_ipsec_crypto_caps_aead_verify(
128                 const struct rte_security_capability *sec_cap,
129                 struct rte_crypto_sym_xform *aead)
130 {
131         const struct rte_cryptodev_symmetric_capability *sym_cap;
132         const struct rte_cryptodev_capabilities *crypto_cap;
133         int j = 0;
134
135         while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
136                         RTE_CRYPTO_OP_TYPE_UNDEFINED) {
137                 if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
138                                 crypto_cap->sym.xform_type == aead->type &&
139                                 crypto_cap->sym.aead.algo == aead->aead.algo) {
140                         sym_cap = &crypto_cap->sym;
141                         if (rte_cryptodev_sym_capability_check_aead(sym_cap,
142                                         aead->aead.key.length,
143                                         aead->aead.digest_length,
144                                         aead->aead.aad_length,
145                                         aead->aead.iv.length) == 0)
146                                 return 0;
147                 }
148         }
149
150         return -ENOTSUP;
151 }
152
153 void
154 test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
155                           struct ipsec_test_data *td_in)
156 {
157         memcpy(td_in, td_out, sizeof(*td_in));
158
159         /* Populate output text of td_in with input text of td_out */
160         memcpy(td_in->output_text.data, td_out->input_text.data,
161                td_out->input_text.len);
162         td_in->output_text.len = td_out->input_text.len;
163
164         /* Populate input text of td_in with output text of td_out */
165         memcpy(td_in->input_text.data, td_out->output_text.data,
166                td_out->output_text.len);
167         td_in->input_text.len = td_out->output_text.len;
168
169         td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
170
171         if (td_in->aead) {
172                 td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
173         } else {
174                 td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
175                 td_in->xform.chain.cipher.cipher.op =
176                                 RTE_CRYPTO_CIPHER_OP_DECRYPT;
177         }
178 }
179
180 static bool
181 is_ipv4(void *ip)
182 {
183         struct rte_ipv4_hdr *ipv4 = ip;
184         uint8_t ip_ver;
185
186         ip_ver = (ipv4->version_ihl & 0xf0) >> RTE_IPV4_IHL_MULTIPLIER;
187         if (ip_ver == IPVERSION)
188                 return true;
189         else
190                 return false;
191 }
192
193 static void
194 test_ipsec_csum_init(void *ip, bool l3, bool l4)
195 {
196         struct rte_ipv4_hdr *ipv4;
197         struct rte_tcp_hdr *tcp;
198         struct rte_udp_hdr *udp;
199         uint8_t next_proto;
200         uint8_t size;
201
202         if (is_ipv4(ip)) {
203                 ipv4 = ip;
204                 size = sizeof(struct rte_ipv4_hdr);
205                 next_proto = ipv4->next_proto_id;
206
207                 if (l3)
208                         ipv4->hdr_checksum = 0;
209         } else {
210                 size = sizeof(struct rte_ipv6_hdr);
211                 next_proto = ((struct rte_ipv6_hdr *)ip)->proto;
212         }
213
214         if (l4) {
215                 switch (next_proto) {
216                 case IPPROTO_TCP:
217                         tcp = (struct rte_tcp_hdr *)RTE_PTR_ADD(ip, size);
218                         tcp->cksum = 0;
219                         break;
220                 case IPPROTO_UDP:
221                         udp = (struct rte_udp_hdr *)RTE_PTR_ADD(ip, size);
222                         udp->dgram_cksum = 0;
223                         break;
224                 default:
225                         return;
226                 }
227         }
228 }
229
230 void
231 test_ipsec_td_prepare(const struct crypto_param *param1,
232                       const struct crypto_param *param2,
233                       const struct ipsec_test_flags *flags,
234                       struct ipsec_test_data *td_array,
235                       int nb_td)
236
237 {
238         struct ipsec_test_data *td;
239         int i;
240
241         memset(td_array, 0, nb_td * sizeof(*td));
242
243         for (i = 0; i < nb_td; i++) {
244                 td = &td_array[i];
245                 /* Copy template for packet & key fields */
246                 memcpy(td, &pkt_aes_256_gcm, sizeof(*td));
247
248                 /* Override fields based on param */
249
250                 if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD)
251                         td->aead = true;
252                 else
253                         td->aead = false;
254
255                 td->xform.aead.aead.algo = param1->alg.aead;
256                 td->xform.aead.aead.key.length = param1->key_length;
257
258                 if (flags->iv_gen)
259                         td->ipsec_xform.options.iv_gen_disable = 0;
260
261                 if (flags->sa_expiry_pkts_soft)
262                         td->ipsec_xform.life.packets_soft_limit =
263                                         IPSEC_TEST_PACKETS_MAX - 1;
264
265                 if (flags->ip_csum) {
266                         td->ipsec_xform.options.ip_csum_enable = 1;
267                         test_ipsec_csum_init(&td->input_text.data, true, false);
268                 }
269
270                 if (flags->l4_csum) {
271                         td->ipsec_xform.options.l4_csum_enable = 1;
272                         test_ipsec_csum_init(&td->input_text.data, false, true);
273                 }
274
275         }
276
277         RTE_SET_USED(param2);
278 }
279
280 void
281 test_ipsec_td_update(struct ipsec_test_data td_inb[],
282                      const struct ipsec_test_data td_outb[],
283                      int nb_td,
284                      const struct ipsec_test_flags *flags)
285 {
286         int i;
287
288         for (i = 0; i < nb_td; i++) {
289                 memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data,
290                        td_outb[i].input_text.len);
291                 td_inb[i].output_text.len = td_outb->input_text.len;
292
293                 if (flags->icv_corrupt) {
294                         int icv_pos = td_inb[i].input_text.len - 4;
295                         td_inb[i].input_text.data[icv_pos] += 1;
296                 }
297
298                 if (flags->sa_expiry_pkts_hard)
299                         td_inb[i].ipsec_xform.life.packets_hard_limit =
300                                         IPSEC_TEST_PACKETS_MAX - 1;
301
302                 if (flags->udp_encap)
303                         td_inb[i].ipsec_xform.options.udp_encap = 1;
304
305                 if (flags->udp_ports_verify)
306                         td_inb[i].ipsec_xform.options.udp_ports_verify = 1;
307
308                 td_inb[i].ipsec_xform.options.tunnel_hdr_verify =
309                         flags->tunnel_hdr_verify;
310
311                 if (flags->ip_csum)
312                         td_inb[i].ipsec_xform.options.ip_csum_enable = 1;
313
314                 if (flags->l4_csum)
315                         td_inb[i].ipsec_xform.options.l4_csum_enable = 1;
316
317                 /* Clear outbound specific flags */
318                 td_inb[i].ipsec_xform.options.iv_gen_disable = 0;
319         }
320 }
321
322 void
323 test_ipsec_display_alg(const struct crypto_param *param1,
324                        const struct crypto_param *param2)
325 {
326         if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD)
327                 printf("\t%s [%d]\n",
328                        rte_crypto_aead_algorithm_strings[param1->alg.aead],
329                        param1->key_length);
330
331         RTE_SET_USED(param2);
332 }
333
334 static int
335 test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
336 {
337         int len = 0;
338
339         if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
340                 if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
341                         if (td->ipsec_xform.tunnel.type ==
342                                         RTE_SECURITY_IPSEC_TUNNEL_IPV4)
343                                 len += sizeof(struct rte_ipv4_hdr);
344                         else
345                                 len += sizeof(struct rte_ipv6_hdr);
346                 }
347         }
348
349         return len;
350 }
351
352 static int
353 test_ipsec_iv_verify_push(struct rte_mbuf *m, const struct ipsec_test_data *td)
354 {
355         static uint8_t iv_queue[IV_LEN_MAX * IPSEC_TEST_PACKETS_MAX];
356         uint8_t *iv_tmp, *output_text = rte_pktmbuf_mtod(m, uint8_t *);
357         int i, iv_pos, iv_len;
358         static int index;
359
360         if (td->aead)
361                 iv_len = td->xform.aead.aead.iv.length - td->salt.len;
362         else
363                 iv_len = td->xform.chain.cipher.cipher.iv.length;
364
365         iv_pos = test_ipsec_tunnel_hdr_len_get(td) + sizeof(struct rte_esp_hdr);
366         output_text += iv_pos;
367
368         TEST_ASSERT(iv_len <= IV_LEN_MAX, "IV length greater than supported");
369
370         /* Compare against previous values */
371         for (i = 0; i < index; i++) {
372                 iv_tmp = &iv_queue[i * IV_LEN_MAX];
373
374                 if (memcmp(output_text, iv_tmp, iv_len) == 0) {
375                         printf("IV repeated");
376                         return TEST_FAILED;
377                 }
378         }
379
380         /* Save IV for future comparisons */
381
382         iv_tmp = &iv_queue[index * IV_LEN_MAX];
383         memcpy(iv_tmp, output_text, iv_len);
384         index++;
385
386         if (index == IPSEC_TEST_PACKETS_MAX)
387                 index = 0;
388
389         return TEST_SUCCESS;
390 }
391
392 static int
393 test_ipsec_l3_csum_verify(struct rte_mbuf *m)
394 {
395         uint16_t actual_cksum, expected_cksum;
396         struct rte_ipv4_hdr *ip;
397
398         ip = rte_pktmbuf_mtod(m, struct rte_ipv4_hdr *);
399
400         if (!is_ipv4((void *)ip))
401                 return TEST_SKIPPED;
402
403         actual_cksum = ip->hdr_checksum;
404
405         ip->hdr_checksum = 0;
406
407         expected_cksum = rte_ipv4_cksum(ip);
408
409         if (actual_cksum != expected_cksum)
410                 return TEST_FAILED;
411
412         return TEST_SUCCESS;
413 }
414
415 static int
416 test_ipsec_l4_csum_verify(struct rte_mbuf *m)
417 {
418         uint16_t actual_cksum = 0, expected_cksum = 0;
419         struct rte_ipv4_hdr *ipv4;
420         struct rte_ipv6_hdr *ipv6;
421         struct rte_tcp_hdr *tcp;
422         struct rte_udp_hdr *udp;
423         void *ip, *l4;
424
425         ip = rte_pktmbuf_mtod(m, void *);
426
427         if (is_ipv4(ip)) {
428                 ipv4 = ip;
429                 l4 = RTE_PTR_ADD(ipv4, sizeof(struct rte_ipv4_hdr));
430
431                 switch (ipv4->next_proto_id) {
432                 case IPPROTO_TCP:
433                         tcp = (struct rte_tcp_hdr *)l4;
434                         actual_cksum = tcp->cksum;
435                         tcp->cksum = 0;
436                         expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
437                         break;
438                 case IPPROTO_UDP:
439                         udp = (struct rte_udp_hdr *)l4;
440                         actual_cksum = udp->dgram_cksum;
441                         udp->dgram_cksum = 0;
442                         expected_cksum = rte_ipv4_udptcp_cksum(ipv4, l4);
443                         break;
444                 default:
445                         break;
446                 }
447         } else {
448                 ipv6 = ip;
449                 l4 = RTE_PTR_ADD(ipv6, sizeof(struct rte_ipv6_hdr));
450
451                 switch (ipv6->proto) {
452                 case IPPROTO_TCP:
453                         tcp = (struct rte_tcp_hdr *)l4;
454                         actual_cksum = tcp->cksum;
455                         tcp->cksum = 0;
456                         expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
457                         break;
458                 case IPPROTO_UDP:
459                         udp = (struct rte_udp_hdr *)l4;
460                         actual_cksum = udp->dgram_cksum;
461                         udp->dgram_cksum = 0;
462                         expected_cksum = rte_ipv6_udptcp_cksum(ipv6, l4);
463                         break;
464                 default:
465                         break;
466                 }
467         }
468
469         if (actual_cksum != expected_cksum)
470                 return TEST_FAILED;
471
472         return TEST_SUCCESS;
473 }
474
475 static int
476 test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td,
477                      bool silent, const struct ipsec_test_flags *flags)
478 {
479         uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
480         uint32_t skip, len = rte_pktmbuf_pkt_len(m);
481         int ret;
482
483         /* For tests with status as error for test success, skip verification */
484         if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
485             (flags->icv_corrupt ||
486              flags->sa_expiry_pkts_hard ||
487              flags->tunnel_hdr_verify))
488                 return TEST_SUCCESS;
489
490         if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS &&
491            flags->udp_encap) {
492                 const struct rte_ipv4_hdr *iph4;
493                 const struct rte_ipv6_hdr *iph6;
494
495                 if (td->ipsec_xform.tunnel.type ==
496                                 RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
497                         iph4 = (const struct rte_ipv4_hdr *)output_text;
498                         if (iph4->next_proto_id != IPPROTO_UDP) {
499                                 printf("UDP header is not found\n");
500                                 return TEST_FAILED;
501                         }
502                 } else {
503                         iph6 = (const struct rte_ipv6_hdr *)output_text;
504                         if (iph6->proto != IPPROTO_UDP) {
505                                 printf("UDP header is not found\n");
506                                 return TEST_FAILED;
507                         }
508                 }
509
510                 len -= sizeof(struct rte_udp_hdr);
511                 output_text += sizeof(struct rte_udp_hdr);
512         }
513
514         if (len != td->output_text.len) {
515                 printf("Output length (%d) not matching with expected (%d)\n",
516                         len, td->output_text.len);
517                 return TEST_FAILED;
518         }
519
520         skip = test_ipsec_tunnel_hdr_len_get(td);
521
522         len -= skip;
523         output_text += skip;
524
525         if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
526                                 flags->ip_csum) {
527                 if (m->ol_flags & PKT_RX_IP_CKSUM_GOOD)
528                         ret = test_ipsec_l3_csum_verify(m);
529                 else
530                         ret = TEST_FAILED;
531
532                 if (ret == TEST_FAILED)
533                         printf("Inner IP checksum test failed\n");
534
535                 return ret;
536         }
537
538         if ((td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
539                                 flags->l4_csum) {
540                 if (m->ol_flags & PKT_RX_L4_CKSUM_GOOD)
541                         ret = test_ipsec_l4_csum_verify(m);
542                 else
543                         ret = TEST_FAILED;
544
545                 if (ret == TEST_FAILED)
546                         printf("Inner L4 checksum test failed\n");
547
548                 return ret;
549         }
550
551
552         if (memcmp(output_text, td->output_text.data + skip, len)) {
553                 if (silent)
554                         return TEST_FAILED;
555
556                 printf("TestCase %s line %d: %s\n", __func__, __LINE__,
557                         "output text not as expected\n");
558
559                 rte_hexdump(stdout, "expected", td->output_text.data + skip,
560                             len);
561                 rte_hexdump(stdout, "actual", output_text, len);
562                 return TEST_FAILED;
563         }
564
565         return TEST_SUCCESS;
566 }
567
568 static int
569 test_ipsec_res_d_prepare(struct rte_mbuf *m, const struct ipsec_test_data *td,
570                    struct ipsec_test_data *res_d)
571 {
572         uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
573         uint32_t len = rte_pktmbuf_pkt_len(m);
574
575         memcpy(res_d, td, sizeof(*res_d));
576         memcpy(res_d->input_text.data, output_text, len);
577         res_d->input_text.len = len;
578
579         res_d->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
580         if (res_d->aead) {
581                 res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
582         } else {
583                 printf("Only AEAD supported\n");
584                 return TEST_SKIPPED;
585         }
586
587         return TEST_SUCCESS;
588 }
589
590 int
591 test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td,
592                         struct ipsec_test_data *res_d, bool silent,
593                         const struct ipsec_test_flags *flags)
594 {
595         int ret;
596
597         if (flags->iv_gen &&
598             td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
599                 ret = test_ipsec_iv_verify_push(m, td);
600                 if (ret != TEST_SUCCESS)
601                         return ret;
602         }
603
604         /*
605          * In case of known vector tests & all inbound tests, res_d provided
606          * would be NULL and output data need to be validated against expected.
607          * For inbound, output_text would be plain packet and for outbound
608          * output_text would IPsec packet. Validate by comparing against
609          * known vectors.
610          *
611          * In case of combined mode tests, the output_text from outbound
612          * operation (ie, IPsec packet) would need to be inbound processed to
613          * obtain the plain text. Copy output_text to result data, 'res_d', so
614          * that inbound processing can be done.
615          */
616
617         if (res_d == NULL)
618                 return test_ipsec_td_verify(m, td, silent, flags);
619         else
620                 return test_ipsec_res_d_prepare(m, td, res_d);
621 }
622
623 int
624 test_ipsec_status_check(struct rte_crypto_op *op,
625                         const struct ipsec_test_flags *flags,
626                         enum rte_security_ipsec_sa_direction dir,
627                         int pkt_num)
628 {
629         int ret = TEST_SUCCESS;
630
631         if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS &&
632             flags->sa_expiry_pkts_hard &&
633             pkt_num == IPSEC_TEST_PACKETS_MAX) {
634                 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
635                         printf("SA hard expiry (pkts) test failed\n");
636                         return TEST_FAILED;
637                 } else {
638                         return TEST_SUCCESS;
639                 }
640         }
641
642         if ((dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) &&
643             flags->tunnel_hdr_verify) {
644                 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
645                         printf("Tunnel header verify test case failed\n");
646                         return TEST_FAILED;
647                 } else {
648                         return TEST_SUCCESS;
649                 }
650         }
651
652         if (dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS && flags->icv_corrupt) {
653                 if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
654                         printf("ICV corruption test case failed\n");
655                         ret = TEST_FAILED;
656                 }
657         } else {
658                 if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
659                         printf("Security op processing failed [pkt_num: %d]\n",
660                                pkt_num);
661                         ret = TEST_FAILED;
662                 }
663         }
664
665         if (flags->sa_expiry_pkts_soft && pkt_num == IPSEC_TEST_PACKETS_MAX) {
666                 if (!(op->aux_flags &
667                       RTE_CRYPTO_OP_AUX_FLAGS_IPSEC_SOFT_EXPIRY)) {
668                         printf("SA soft expiry (pkts) test failed\n");
669                         ret = TEST_FAILED;
670                 }
671         }
672
673         return ret;
674 }