test/crypto: add lookaside IPsec cases
[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_ip.h>
8 #include <rte_security.h>
9
10 #include "test.h"
11 #include "test_cryptodev_security_ipsec.h"
12
13 int
14 test_ipsec_sec_caps_verify(struct rte_security_ipsec_xform *ipsec_xform,
15                            const struct rte_security_capability *sec_cap,
16                            bool silent)
17 {
18         /* Verify security capabilities */
19
20         if (ipsec_xform->options.esn == 1 && sec_cap->ipsec.options.esn == 0) {
21                 if (!silent)
22                         RTE_LOG(INFO, USER1, "ESN is not supported\n");
23                 return -ENOTSUP;
24         }
25
26         if (ipsec_xform->options.udp_encap == 1 &&
27             sec_cap->ipsec.options.udp_encap == 0) {
28                 if (!silent)
29                         RTE_LOG(INFO, USER1, "UDP encapsulation is not supported\n");
30                 return -ENOTSUP;
31         }
32
33         if (ipsec_xform->options.copy_dscp == 1 &&
34             sec_cap->ipsec.options.copy_dscp == 0) {
35                 if (!silent)
36                         RTE_LOG(INFO, USER1, "Copy DSCP is not supported\n");
37                 return -ENOTSUP;
38         }
39
40         if (ipsec_xform->options.copy_flabel == 1 &&
41             sec_cap->ipsec.options.copy_flabel == 0) {
42                 if (!silent)
43                         RTE_LOG(INFO, USER1, "Copy Flow Label is not supported\n");
44                 return -ENOTSUP;
45         }
46
47         if (ipsec_xform->options.copy_df == 1 &&
48             sec_cap->ipsec.options.copy_df == 0) {
49                 if (!silent)
50                         RTE_LOG(INFO, USER1, "Copy DP bit is not supported\n");
51                 return -ENOTSUP;
52         }
53
54         if (ipsec_xform->options.dec_ttl == 1 &&
55             sec_cap->ipsec.options.dec_ttl == 0) {
56                 if (!silent)
57                         RTE_LOG(INFO, USER1, "Decrement TTL is not supported\n");
58                 return -ENOTSUP;
59         }
60
61         if (ipsec_xform->options.ecn == 1 && sec_cap->ipsec.options.ecn == 0) {
62                 if (!silent)
63                         RTE_LOG(INFO, USER1, "ECN is not supported\n");
64                 return -ENOTSUP;
65         }
66
67         if (ipsec_xform->options.stats == 1 &&
68             sec_cap->ipsec.options.stats == 0) {
69                 if (!silent)
70                         RTE_LOG(INFO, USER1, "Stats is not supported\n");
71                 return -ENOTSUP;
72         }
73
74         return 0;
75 }
76
77 int
78 test_ipsec_crypto_caps_aead_verify(
79                 const struct rte_security_capability *sec_cap,
80                 struct rte_crypto_sym_xform *aead)
81 {
82         const struct rte_cryptodev_symmetric_capability *sym_cap;
83         const struct rte_cryptodev_capabilities *crypto_cap;
84         int j = 0;
85
86         while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
87                         RTE_CRYPTO_OP_TYPE_UNDEFINED) {
88                 if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
89                                 crypto_cap->sym.xform_type == aead->type &&
90                                 crypto_cap->sym.aead.algo == aead->aead.algo) {
91                         sym_cap = &crypto_cap->sym;
92                         if (rte_cryptodev_sym_capability_check_aead(sym_cap,
93                                         aead->aead.key.length,
94                                         aead->aead.digest_length,
95                                         aead->aead.aad_length,
96                                         aead->aead.iv.length) == 0)
97                                 return 0;
98                 }
99         }
100
101         return -ENOTSUP;
102 }
103
104 void
105 test_ipsec_td_in_from_out(const struct ipsec_test_data *td_out,
106                           struct ipsec_test_data *td_in)
107 {
108         memcpy(td_in, td_out, sizeof(*td_in));
109
110         /* Populate output text of td_in with input text of td_out */
111         memcpy(td_in->output_text.data, td_out->input_text.data,
112                td_out->input_text.len);
113         td_in->output_text.len = td_out->input_text.len;
114
115         /* Populate input text of td_in with output text of td_out */
116         memcpy(td_in->input_text.data, td_out->output_text.data,
117                td_out->output_text.len);
118         td_in->input_text.len = td_out->output_text.len;
119
120         td_in->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
121
122         if (td_in->aead) {
123                 td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
124         } else {
125                 td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
126                 td_in->xform.chain.cipher.cipher.op =
127                                 RTE_CRYPTO_CIPHER_OP_DECRYPT;
128         }
129 }
130
131 static int
132 test_ipsec_tunnel_hdr_len_get(const struct ipsec_test_data *td)
133 {
134         int len = 0;
135
136         if (td->ipsec_xform.direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
137                 if (td->ipsec_xform.mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
138                         if (td->ipsec_xform.tunnel.type ==
139                                         RTE_SECURITY_IPSEC_TUNNEL_IPV4)
140                                 len += sizeof(struct rte_ipv4_hdr);
141                         else
142                                 len += sizeof(struct rte_ipv6_hdr);
143                 }
144         }
145
146         return len;
147 }
148
149 static int
150 test_ipsec_td_verify(struct rte_mbuf *m, const struct ipsec_test_data *td,
151                      bool silent)
152 {
153         uint8_t *output_text = rte_pktmbuf_mtod(m, uint8_t *);
154         uint32_t skip, len = rte_pktmbuf_pkt_len(m);
155
156         if (len != td->output_text.len) {
157                 printf("Output length (%d) not matching with expected (%d)\n",
158                         len, td->output_text.len);
159                 return TEST_FAILED;
160         }
161
162         skip = test_ipsec_tunnel_hdr_len_get(td);
163
164         len -= skip;
165         output_text += skip;
166
167         if (memcmp(output_text, td->output_text.data + skip, len)) {
168                 if (silent)
169                         return TEST_FAILED;
170
171                 printf("TestCase %s line %d: %s\n", __func__, __LINE__,
172                         "output text not as expected\n");
173
174                 rte_hexdump(stdout, "expected", td->output_text.data + skip,
175                             len);
176                 rte_hexdump(stdout, "actual", output_text, len);
177                 return TEST_FAILED;
178         }
179
180         return TEST_SUCCESS;
181 }
182
183 int
184 test_ipsec_post_process(struct rte_mbuf *m, const struct ipsec_test_data *td,
185                         struct ipsec_test_data *res_d, bool silent)
186 {
187         /*
188          * In case of known vector tests & all inbound tests, res_d provided
189          * would be NULL and output data need to be validated against expected.
190          * For inbound, output_text would be plain packet and for outbound
191          * output_text would IPsec packet. Validate by comparing against
192          * known vectors.
193          */
194         RTE_SET_USED(res_d);
195         return test_ipsec_td_verify(m, td, silent);
196 }
197
198 int
199 test_ipsec_status_check(struct rte_crypto_op *op,
200                         enum rte_security_ipsec_sa_direction dir)
201 {
202         int ret = TEST_SUCCESS;
203
204         if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
205                 printf("Security op processing failed\n");
206                 ret = TEST_FAILED;
207         }
208
209         RTE_SET_USED(dir);
210
211         return ret;
212 }