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