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