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