xref: /dpdk/app/test/test_cryptodev_security_tls_record.c (revision 625110ef5482d9a814073c6eb7940e318d806a22)
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
test_tls_record_status_check(struct rte_crypto_op * op,const struct tls_record_test_data * td)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
test_tls_record_sec_caps_verify(struct rte_security_tls_record_xform * tls_record_xform,const struct rte_security_capability * sec_cap,bool silent)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
test_tls_record_td_read_from_write(const struct tls_record_test_data * td_out,struct tls_record_test_data * td_in)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
test_tls_record_td_prepare(const struct crypto_param * param1,const struct crypto_param * param2,const struct tls_record_test_flags * flags,struct tls_record_test_data * td_array,int nb_td,unsigned int data_len)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
test_tls_record_td_update(struct tls_record_test_data td_inb[],const struct tls_record_test_data td_outb[],int nb_td,const struct tls_record_test_flags * flags)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 		/* Corrupt a byte in the last but one block */
219 		if (flags->padding_corruption) {
220 			int offset = td_inb[i].input_text.len - TLS_RECORD_PAD_CORRUPT_OFFSET;
221 
222 			td_inb[i].input_text.data[offset] = ~td_inb[i].input_text.data[offset];
223 		}
224 
225 		/* Clear outbound specific flags */
226 		td_inb[i].tls_record_xform.options.iv_gen_disable = 0;
227 	}
228 
229 	RTE_SET_USED(flags);
230 }
231 
232 static int
test_tls_record_td_verify(uint8_t * output_text,uint32_t len,const struct tls_record_test_data * td,bool silent)233 test_tls_record_td_verify(uint8_t *output_text, uint32_t len, const struct tls_record_test_data *td,
234 			 bool silent)
235 {
236 	if (len != td->output_text.len) {
237 		printf("Output length (%d) not matching with expected (%d)\n",
238 			len, td->output_text.len);
239 		return TEST_FAILED;
240 	}
241 
242 	if (memcmp(output_text, td->output_text.data, len)) {
243 		if (silent)
244 			return TEST_FAILED;
245 
246 		printf("[%s : %d] %s\n", __func__, __LINE__, "Output text not as expected\n");
247 
248 		rte_hexdump(stdout, "expected", td->output_text.data, len);
249 		rte_hexdump(stdout, "actual", output_text, len);
250 		return TEST_FAILED;
251 	}
252 
253 	return TEST_SUCCESS;
254 }
255 
256 static int
test_tls_record_res_d_prepare(const uint8_t * output_text,uint32_t len,const struct tls_record_test_data * td,struct tls_record_test_data * res_d)257 test_tls_record_res_d_prepare(const uint8_t *output_text, uint32_t len,
258 			      const struct tls_record_test_data *td,
259 			      struct tls_record_test_data *res_d)
260 {
261 	memcpy(res_d, td, sizeof(*res_d));
262 
263 	memcpy(&res_d->input_text.data, output_text, len);
264 	res_d->input_text.len = len;
265 	res_d->output_text.len = td->input_text.len;
266 
267 	res_d->tls_record_xform.type = RTE_SECURITY_TLS_SESS_TYPE_READ;
268 	if (res_d->aead) {
269 		res_d->xform.aead.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
270 	} else {
271 		res_d->xform.chain.cipher.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
272 		res_d->xform.chain.auth.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
273 	}
274 
275 	return TEST_SUCCESS;
276 }
277 
278 static int
tls_record_hdr_verify(const struct tls_record_test_data * td,const uint8_t * output_text,const struct tls_record_test_flags * flags)279 tls_record_hdr_verify(const struct tls_record_test_data *td, const uint8_t *output_text,
280 		      const struct tls_record_test_flags *flags)
281 {
282 	uint16_t length, hdr_len;
283 	uint8_t content_type;
284 
285 	if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_TLS_1_2) {
286 		const struct rte_tls_hdr *hdr = (const struct rte_tls_hdr *)output_text;
287 		if (rte_be_to_cpu_16(hdr->version) != RTE_TLS_VERSION_1_2) {
288 			printf("Incorrect header version [expected - %4x, received - %4x]\n",
289 			       RTE_TLS_VERSION_1_2, rte_be_to_cpu_16(hdr->version));
290 			return TEST_FAILED;
291 		}
292 		content_type = hdr->type;
293 		length = rte_be_to_cpu_16(hdr->length);
294 		hdr_len = sizeof(struct rte_tls_hdr);
295 	} else if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_TLS_1_3) {
296 		const struct rte_tls_hdr *hdr = (const struct rte_tls_hdr *)output_text;
297 		if (rte_be_to_cpu_16(hdr->version) != RTE_TLS_VERSION_1_2) {
298 			printf("Incorrect header version [expected - %4x, received - %4x]\n",
299 			       RTE_TLS_VERSION_1_2, rte_be_to_cpu_16(hdr->version));
300 			return TEST_FAILED;
301 		}
302 		content_type = hdr->type;
303 		length = rte_be_to_cpu_16(hdr->length);
304 		hdr_len = sizeof(struct rte_tls_hdr);
305 	} else if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_DTLS_1_2) {
306 		const struct rte_dtls_hdr *hdr = (const struct rte_dtls_hdr *)output_text;
307 		if (rte_be_to_cpu_16(hdr->version) != RTE_DTLS_VERSION_1_2) {
308 			printf("Incorrect header version [expected - %4x, received - %4x]\n",
309 			       RTE_DTLS_VERSION_1_2, rte_be_to_cpu_16(hdr->version));
310 			return TEST_FAILED;
311 		}
312 		content_type = hdr->type;
313 		length = rte_be_to_cpu_16(hdr->length);
314 		hdr_len = sizeof(struct rte_dtls_hdr);
315 	} else {
316 		return TEST_FAILED;
317 	}
318 
319 	if (td->tls_record_xform.ver == RTE_SECURITY_VERSION_TLS_1_3) {
320 		if (content_type != RTE_TLS_TYPE_APPDATA) {
321 			printf("Incorrect content type in packet [expected - %d, received - %d]\n",
322 			       td->app_type, content_type);
323 			return TEST_FAILED;
324 		}
325 	} else {
326 		if (content_type != td->app_type) {
327 			printf("Incorrect content type in packet [expected - %d, received - %d]\n",
328 			       td->app_type, content_type);
329 			return TEST_FAILED;
330 		}
331 	}
332 
333 	if (!flags->opt_padding) {
334 		if (length != td->output_text.len - hdr_len) {
335 			printf("Incorrect packet length [expected - %d, received - %d]\n",
336 			       td->output_text.len - hdr_len, length);
337 			return TEST_FAILED;
338 		}
339 	} else {
340 		int pad_len = (flags->opt_padding * 8) > 256 ? 256 : (flags->opt_padding * 8);
341 		int expect_len = td->output_text.len - hdr_len + pad_len;
342 
343 		if (length - expect_len > 32) {
344 			printf("Incorrect packet length [expected - %d, received - %d]\n",
345 			       expect_len, length);
346 			return TEST_FAILED;
347 		}
348 
349 	}
350 
351 	return TEST_SUCCESS;
352 }
353 
354 int
test_tls_record_post_process(const struct rte_mbuf * m,const struct tls_record_test_data * td,struct tls_record_test_data * res_d,bool silent,const struct tls_record_test_flags * flags)355 test_tls_record_post_process(const struct rte_mbuf *m, const struct tls_record_test_data *td,
356 			     struct tls_record_test_data *res_d, bool silent,
357 			     const struct tls_record_test_flags *flags)
358 {
359 	uint8_t output_text[TEST_SEC_CIPHERTEXT_MAX_LEN];
360 	uint32_t len = rte_pktmbuf_pkt_len(m), data_len;
361 	const struct rte_mbuf *seg;
362 	const uint8_t *output;
363 	int ret;
364 
365 	memset(output_text, 0, TEST_SEC_CIPHERTEXT_MAX_LEN);
366 
367 	/*
368 	 * Actual data in packet might be less in error cases, hence take minimum of pkt_len and sum
369 	 * of data_len. This is done to run through negative test cases.
370 	 */
371 	data_len = 0;
372 	seg = m;
373 	while (seg) {
374 		data_len += seg->data_len;
375 		seg = seg->next;
376 	}
377 
378 	len = RTE_MIN(len, data_len);
379 	TEST_ASSERT(len <= TEST_SEC_CIPHERTEXT_MAX_LEN, "Invalid packet length: %u", len);
380 
381 	/* Copy mbuf payload to continuous buffer */
382 	output = rte_pktmbuf_read(m, 0, len, output_text);
383 	if (output != output_text) {
384 		/* Single segment mbuf, copy manually */
385 		memcpy(output_text, output, len);
386 	}
387 
388 	if (td->tls_record_xform.type == RTE_SECURITY_TLS_SESS_TYPE_WRITE) {
389 		ret = tls_record_hdr_verify(td, output_text, flags);
390 		if (ret != TEST_SUCCESS)
391 			return ret;
392 	}
393 
394 	/*
395 	 * In case of known vector tests & all record read (decrypt) tests, res_d provided would be
396 	 * NULL and output data need to be validated against expected. For record read (decrypt),
397 	 * output_text would be plain payload and for record write (encrypt), output_text would TLS
398 	 * record. Validate by comparing against known vectors.
399 	 *
400 	 * In case of combined mode tests, the output_text from TLS write (encrypt) operation (ie,
401 	 * TLS record) would need to be decrypted using a TLS read operation to obtain the plain
402 	 * text. Copy output_text to result data, 'res_d', so that inbound processing can be done.
403 	 */
404 
405 	if (res_d == NULL)
406 		return test_tls_record_td_verify(output_text, len, td, silent);
407 	else
408 		return test_tls_record_res_d_prepare(output_text, len, td, res_d);
409 }
410