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