xref: /dpdk/app/test/test_cryptodev_security_tls_record.c (revision d2379dd8f27f4ecb54b51b74529f2543b18cfd33)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2023 Marvell.
3  */
4 
5 #include <rte_crypto.h>
6 #include <rte_dtls.h>
7 #include <rte_tls.h>
8 
9 #include "test.h"
10 #include "test_cryptodev_security_tls_record.h"
11 #include "test_cryptodev_security_tls_record_test_vectors.h"
12 #include "test_security_proto.h"
13 
14 int
15 test_tls_record_status_check(struct rte_crypto_op *op,
16 			     const struct tls_record_test_data *td)
17 {
18 	int ret = TEST_SUCCESS;
19 
20 	if ((td->tls_record_xform.type == RTE_SECURITY_TLS_SESS_TYPE_READ) &&
21 	     td->ar_packet) {
22 		if (op->status != RTE_CRYPTO_OP_STATUS_ERROR) {
23 			printf("Anti replay test case failed\n");
24 			return TEST_FAILED;
25 		} else {
26 			return TEST_SUCCESS;
27 		}
28 	}
29 
30 	if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS)
31 		ret = TEST_FAILED;
32 
33 	return ret;
34 }
35 
36 int
37 test_tls_record_sec_caps_verify(struct rte_security_tls_record_xform *tls_record_xform,
38 				const struct rte_security_capability *sec_cap, bool silent)
39 {
40 	/* Verify security capabilities */
41 
42 	RTE_SET_USED(tls_record_xform);
43 	RTE_SET_USED(sec_cap);
44 	RTE_SET_USED(silent);
45 
46 	return 0;
47 }
48 
49 void
50 test_tls_record_td_read_from_write(const struct tls_record_test_data *td_out,
51 				   struct tls_record_test_data *td_in)
52 {
53 	memcpy(td_in, td_out, sizeof(*td_in));
54 
55 	/* Populate output text of td_in with input text of td_out */
56 	memcpy(td_in->output_text.data, td_out->input_text.data, td_out->input_text.len);
57 	td_in->output_text.len = td_out->input_text.len;
58 
59 	/* Populate input text of td_in with output text of td_out */
60 	memcpy(td_in->input_text.data, td_out->output_text.data, td_out->output_text.len);
61 	td_in->input_text.len = td_out->output_text.len;
62 
63 	td_in->tls_record_xform.type = RTE_SECURITY_TLS_SESS_TYPE_READ;
64 
65 	if (td_in->aead) {
66 		td_in->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
67 	} else {
68 		td_in->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
69 		td_in->xform.chain.cipher.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
70 	}
71 }
72 
73 int
74 test_tls_record_td_prepare(const struct crypto_param *param1, const struct crypto_param *param2,
75 			   const struct tls_record_test_flags *flags,
76 			   struct tls_record_test_data *td_array,
77 			   int nb_td, unsigned int data_len)
78 {
79 	int i, min_padding, hdr_len, tls_pkt_size, mac_len = 0, exp_nonce_len = 0, roundup_len = 0;
80 	struct tls_record_test_data *td = NULL;
81 
82 	if ((flags->tls_version == RTE_SECURITY_VERSION_TLS_1_3) &&
83 	    (param1->type != RTE_CRYPTO_SYM_XFORM_AEAD))
84 		return TEST_SKIPPED;
85 
86 	memset(td_array, 0, nb_td * sizeof(*td));
87 
88 	for (i = 0; i < nb_td; i++) {
89 		td = &td_array[i];
90 
91 		/* Prepare fields based on param */
92 
93 		if (param1->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
94 			/* Copy template for packet & key fields */
95 			switch (flags->tls_version) {
96 			case RTE_SECURITY_VERSION_TLS_1_2:
97 				memcpy(td, &tls_test_data_aes_128_gcm_v1, sizeof(*td));
98 				break;
99 			case RTE_SECURITY_VERSION_DTLS_1_2:
100 				memcpy(td, &dtls_test_data_aes_128_gcm, sizeof(*td));
101 				break;
102 			case RTE_SECURITY_VERSION_TLS_1_3:
103 				memcpy(td, &tls13_test_data_aes_128_gcm, sizeof(*td));
104 				break;
105 			}
106 
107 			td->aead = true;
108 			td->xform.aead.aead.algo = param1->alg.aead;
109 			td->xform.aead.aead.key.length = param1->key_length;
110 			td->xform.aead.aead.digest_length = param1->digest_length;
111 		} else {
112 			/* Copy template for packet & key fields */
113 			if (flags->tls_version == RTE_SECURITY_VERSION_DTLS_1_2)
114 				memcpy(td, &dtls_test_data_aes_128_cbc_sha1_hmac, sizeof(*td));
115 			else
116 				memcpy(td, &tls_test_data_aes_128_cbc_sha1_hmac, sizeof(*td));
117 
118 			td->aead = false;
119 			td->xform.chain.cipher.cipher.algo = param1->alg.cipher;
120 			td->xform.chain.cipher.cipher.key.length = param1->key_length;
121 			td->xform.chain.cipher.cipher.iv.length = param1->iv_length;
122 			td->xform.chain.auth.auth.algo = param2->alg.auth;
123 			td->xform.chain.auth.auth.key.length = param2->key_length;
124 			td->xform.chain.auth.auth.digest_length = param2->digest_length;
125 		}
126 
127 		if (flags->data_walkthrough || flags->zero_len) {
128 			test_sec_proto_pattern_set(td->input_text.data, data_len);
129 			td->input_text.len = data_len;
130 		}
131 
132 		if (flags->content_type == TLS_RECORD_TEST_CONTENT_TYPE_CUSTOM)
133 			td->app_type = RTE_TLS_TYPE_MAX;
134 		else if (flags->content_type == TLS_RECORD_TEST_CONTENT_TYPE_HANDSHAKE)
135 			td->app_type = RTE_TLS_TYPE_HANDSHAKE;
136 
137 		tls_pkt_size = td->input_text.len;
138 
139 		if (!td->aead) {
140 			mac_len = td->xform.chain.auth.auth.digest_length;
141 			min_padding = 1;
142 			switch (td->xform.chain.cipher.cipher.algo) {
143 			case RTE_CRYPTO_CIPHER_3DES_CBC:
144 				roundup_len = 8;
145 				exp_nonce_len = 8;
146 				break;
147 			case RTE_CRYPTO_CIPHER_AES_CBC:
148 				roundup_len = 16;
149 				exp_nonce_len = 16;
150 				break;
151 			default:
152 				roundup_len = 0;
153 				exp_nonce_len = 0;
154 				break;
155 			}
156 		} else {
157 			mac_len = td->xform.aead.aead.digest_length;
158 			min_padding = 0;
159 			roundup_len = 0;
160 			if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_TLS_1_3)
161 				exp_nonce_len = 0;
162 			else
163 				exp_nonce_len = 8;
164 		}
165 
166 		switch (td->tls_record_xform.ver) {
167 		case RTE_SECURITY_VERSION_TLS_1_2:
168 			hdr_len = sizeof(struct rte_tls_hdr);
169 			break;
170 		case RTE_SECURITY_VERSION_TLS_1_3:
171 			hdr_len = sizeof(struct rte_tls_hdr);
172 			/* Add 1 byte for content type in packet */
173 			tls_pkt_size += 1;
174 			break;
175 		case RTE_SECURITY_VERSION_DTLS_1_2:
176 			hdr_len = sizeof(struct rte_dtls_hdr);
177 			break;
178 		default:
179 			return TEST_SKIPPED;
180 		}
181 
182 		tls_pkt_size += mac_len;
183 
184 		/* Padding */
185 		tls_pkt_size += min_padding;
186 
187 		if (roundup_len)
188 			tls_pkt_size = RTE_ALIGN_MUL_CEIL(tls_pkt_size, roundup_len);
189 
190 		/* Explicit nonce */
191 		tls_pkt_size += exp_nonce_len;
192 
193 		/* Add TLS header */
194 		tls_pkt_size += hdr_len;
195 
196 		td->output_text.len = tls_pkt_size;
197 
198 	}
199 	return TEST_SUCCESS;
200 }
201 
202 void
203 test_tls_record_td_update(struct tls_record_test_data td_inb[],
204 			  const struct tls_record_test_data td_outb[], int nb_td,
205 			  const struct tls_record_test_flags *flags)
206 {
207 	int i;
208 
209 	for (i = 0; i < nb_td; i++) {
210 		memcpy(td_inb[i].output_text.data, td_outb[i].input_text.data,
211 		       td_outb[i].input_text.len);
212 		td_inb[i].output_text.len = td_outb->input_text.len;
213 
214 		/* Corrupt the content type in the TLS header of encrypted packet */
215 		if (flags->pkt_corruption)
216 			td_inb[i].input_text.data[0] = ~td_inb[i].input_text.data[0];
217 
218 		/* Clear outbound specific flags */
219 		td_inb[i].tls_record_xform.options.iv_gen_disable = 0;
220 	}
221 
222 	RTE_SET_USED(flags);
223 }
224 
225 static int
226 test_tls_record_td_verify(uint8_t *output_text, uint32_t len, const struct tls_record_test_data *td,
227 			 bool silent)
228 {
229 	if (len != td->output_text.len) {
230 		printf("Output length (%d) not matching with expected (%d)\n",
231 			len, td->output_text.len);
232 		return TEST_FAILED;
233 	}
234 
235 	if (memcmp(output_text, td->output_text.data, len)) {
236 		if (silent)
237 			return TEST_FAILED;
238 
239 		printf("[%s : %d] %s\n", __func__, __LINE__, "Output text not as expected\n");
240 
241 		rte_hexdump(stdout, "expected", td->output_text.data, len);
242 		rte_hexdump(stdout, "actual", output_text, len);
243 		return TEST_FAILED;
244 	}
245 
246 	return TEST_SUCCESS;
247 }
248 
249 static int
250 test_tls_record_res_d_prepare(const uint8_t *output_text, uint32_t len,
251 			      const struct tls_record_test_data *td,
252 			      struct tls_record_test_data *res_d)
253 {
254 	memcpy(res_d, td, sizeof(*res_d));
255 
256 	memcpy(&res_d->input_text.data, output_text, len);
257 	res_d->input_text.len = len;
258 	res_d->output_text.len = td->input_text.len;
259 
260 	res_d->tls_record_xform.type = RTE_SECURITY_TLS_SESS_TYPE_READ;
261 	if (res_d->aead) {
262 		res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
263 	} else {
264 		res_d->xform.chain.cipher.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
265 		res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
266 	}
267 
268 	return TEST_SUCCESS;
269 }
270 
271 static int
272 tls_record_hdr_verify(const struct tls_record_test_data *td, const uint8_t *output_text)
273 {
274 	uint16_t length, hdr_len;
275 	uint8_t content_type;
276 
277 	if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_TLS_1_2) {
278 		const struct rte_tls_hdr *hdr = (const struct rte_tls_hdr *)output_text;
279 		if (rte_be_to_cpu_16(hdr->version) != RTE_TLS_VERSION_1_2) {
280 			printf("Incorrect header version [expected - %4x, received - %4x]\n",
281 			       RTE_TLS_VERSION_1_2, rte_be_to_cpu_16(hdr->version));
282 			return TEST_FAILED;
283 		}
284 		content_type = hdr->type;
285 		length = rte_be_to_cpu_16(hdr->length);
286 		hdr_len = sizeof(struct rte_tls_hdr);
287 	} else if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_TLS_1_3) {
288 		const struct rte_tls_hdr *hdr = (const struct rte_tls_hdr *)output_text;
289 		if (rte_be_to_cpu_16(hdr->version) != RTE_TLS_VERSION_1_2) {
290 			printf("Incorrect header version [expected - %4x, received - %4x]\n",
291 			       RTE_TLS_VERSION_1_2, rte_be_to_cpu_16(hdr->version));
292 			return TEST_FAILED;
293 		}
294 		content_type = hdr->type;
295 		length = rte_be_to_cpu_16(hdr->length);
296 		hdr_len = sizeof(struct rte_tls_hdr);
297 	} else if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_DTLS_1_2) {
298 		const struct rte_dtls_hdr *hdr = (const struct rte_dtls_hdr *)output_text;
299 		if (rte_be_to_cpu_16(hdr->version) != RTE_DTLS_VERSION_1_2) {
300 			printf("Incorrect header version [expected - %4x, received - %4x]\n",
301 			       RTE_DTLS_VERSION_1_2, rte_be_to_cpu_16(hdr->version));
302 			return TEST_FAILED;
303 		}
304 		content_type = hdr->type;
305 		length = rte_be_to_cpu_16(hdr->length);
306 		hdr_len = sizeof(struct rte_dtls_hdr);
307 	} else {
308 		return TEST_FAILED;
309 	}
310 
311 	if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_TLS_1_3) {
312 		if (content_type != RTE_TLS_TYPE_APPDATA) {
313 			printf("Incorrect content type in packet [expected - %d, received - %d]\n",
314 			       td->app_type, content_type);
315 			return TEST_FAILED;
316 		}
317 	} else {
318 		if (content_type != td->app_type) {
319 			printf("Incorrect content type in packet [expected - %d, received - %d]\n",
320 			       td->app_type, content_type);
321 			return TEST_FAILED;
322 		}
323 	}
324 
325 	if (length != td->output_text.len - hdr_len) {
326 		printf("Incorrect packet length [expected - %d, received - %d]\n",
327 		       td->output_text.len - hdr_len, length);
328 		return TEST_FAILED;
329 	}
330 
331 	return TEST_SUCCESS;
332 }
333 
334 int
335 test_tls_record_post_process(const struct rte_mbuf *m, const struct tls_record_test_data *td,
336 			     struct tls_record_test_data *res_d, bool silent)
337 {
338 	uint8_t output_text[TEST_SEC_CIPHERTEXT_MAX_LEN];
339 	uint32_t len = rte_pktmbuf_pkt_len(m), data_len;
340 	const struct rte_mbuf *seg;
341 	const uint8_t *output;
342 	int ret;
343 
344 	memset(output_text, 0, TEST_SEC_CIPHERTEXT_MAX_LEN);
345 
346 	/*
347 	 * Actual data in packet might be less in error cases, hence take minimum of pkt_len and sum
348 	 * of data_len. This is done to run through negative test cases.
349 	 */
350 	data_len = 0;
351 	seg = m;
352 	while (seg) {
353 		data_len += seg->data_len;
354 		seg = seg->next;
355 	}
356 
357 	len = RTE_MIN(len, data_len);
358 	TEST_ASSERT(len <= TEST_SEC_CIPHERTEXT_MAX_LEN, "Invalid packet length: %u", len);
359 
360 	/* Copy mbuf payload to continuous buffer */
361 	output = rte_pktmbuf_read(m, 0, len, output_text);
362 	if (output != output_text) {
363 		/* Single segment mbuf, copy manually */
364 		memcpy(output_text, output, len);
365 	}
366 
367 	if (td->tls_record_xform.type == RTE_SECURITY_TLS_SESS_TYPE_WRITE) {
368 		ret = tls_record_hdr_verify(td, output_text);
369 		if (ret != TEST_SUCCESS)
370 			return ret;
371 	}
372 
373 	/*
374 	 * In case of known vector tests & all record read (decrypt) tests, res_d provided would be
375 	 * NULL and output data need to be validated against expected. For record read (decrypt),
376 	 * output_text would be plain payload and for record write (encrypt), output_text would TLS
377 	 * record. Validate by comparing against known vectors.
378 	 *
379 	 * In case of combined mode tests, the output_text from TLS write (encrypt) operation (ie,
380 	 * TLS record) would need to be decrypted using a TLS read operation to obtain the plain
381 	 * text. Copy output_text to result data, 'res_d', so that inbound processing can be done.
382 	 */
383 
384 	if (res_d == NULL)
385 		return test_tls_record_td_verify(output_text, len, td, silent);
386 	else
387 		return test_tls_record_res_d_prepare(output_text, len, td, res_d);
388 }
389