+ const struct rte_cryptodev_symmetric_capability *cap;
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ struct rte_crypto_auth_xform *auth_xform = &xform->auth;
+
+ xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+ auth_xform->algo = RTE_CRYPTO_AUTH_AES_CMAC;
+ auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+ RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY;
+ auth_xform->digest_length = vec.cipher_auth.digest.len;
+ auth_xform->key.data = vec.cipher_auth.key.val;
+ auth_xform->key.length = vec.cipher_auth.key.len;
+
+ cap_idx.algo.auth = auth_xform->algo;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+ cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
+ if (!cap) {
+ RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
+ env.dev_id);
+ return -EINVAL;
+ }
+
+ if (rte_cryptodev_sym_capability_check_auth(cap,
+ auth_xform->key.length,
+ auth_xform->digest_length, 0) != 0) {
+ RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
+ info.device_name, auth_xform->key.length,
+ auth_xform->digest_length);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int
+prepare_ccm_xform(struct rte_crypto_sym_xform *xform)
+{
+ const struct rte_cryptodev_symmetric_capability *cap;
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ struct rte_crypto_aead_xform *aead_xform = &xform->aead;
+
+ xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+ aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM;
+ aead_xform->aad_length = vec.aead.aad.len;
+ aead_xform->digest_length = vec.aead.digest.len;
+ aead_xform->iv.offset = IV_OFF;
+ aead_xform->iv.length = vec.iv.len;
+ aead_xform->key.data = vec.aead.key.val;
+ aead_xform->key.length = vec.aead.key.len;
+ aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+ RTE_CRYPTO_AEAD_OP_ENCRYPT :
+ RTE_CRYPTO_AEAD_OP_DECRYPT;
+
+ cap_idx.algo.aead = aead_xform->algo;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+
+ cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
+ if (!cap) {
+ RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
+ env.dev_id);
+ return -EINVAL;
+ }
+
+ if (rte_cryptodev_sym_capability_check_aead(cap,
+ aead_xform->key.length,
+ aead_xform->digest_length, aead_xform->aad_length,
+ aead_xform->iv.length) != 0) {
+ RTE_LOG(ERR, USER1,
+ "PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n",
+ info.device_name, aead_xform->key.length,
+ aead_xform->digest_length,
+ aead_xform->aad_length,
+ aead_xform->iv.length);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int
+prepare_sha_xform(struct rte_crypto_sym_xform *xform)
+{
+ const struct rte_cryptodev_symmetric_capability *cap;
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ struct rte_crypto_auth_xform *auth_xform = &xform->auth;
+
+ xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+ auth_xform->algo = info.interim_info.sha_data.algo;
+ auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE;
+ auth_xform->digest_length = vec.cipher_auth.digest.len;
+
+ cap_idx.algo.auth = auth_xform->algo;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+ cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
+ if (!cap) {
+ RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
+ env.dev_id);
+ return -EINVAL;
+ }
+
+ if (rte_cryptodev_sym_capability_check_auth(cap,
+ auth_xform->key.length,
+ auth_xform->digest_length, 0) != 0) {
+ RTE_LOG(ERR, USER1, "PMD %s key length %u digest length %u\n",
+ info.device_name, auth_xform->key.length,
+ auth_xform->digest_length);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int
+prepare_xts_xform(struct rte_crypto_sym_xform *xform)
+{
+ const struct rte_cryptodev_symmetric_capability *cap;
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher;
+
+ xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+ cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_XTS;
+ cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ?
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT :
+ RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ cipher_xform->key.data = vec.cipher_auth.key.val;
+ cipher_xform->key.length = vec.cipher_auth.key.len;
+ cipher_xform->iv.length = vec.iv.len;
+ cipher_xform->iv.offset = IV_OFF;
+
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_XTS;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+
+ cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx);
+ if (!cap) {
+ RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n",
+ env.dev_id);
+ return -EINVAL;
+ }
+
+ if (rte_cryptodev_sym_capability_check_cipher(cap,
+ cipher_xform->key.length,
+ cipher_xform->iv.length) != 0) {
+ RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n",
+ info.device_name, cipher_xform->key.length,
+ cipher_xform->iv.length);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int
+get_writeback_data(struct fips_val *val)
+{
+ struct rte_mbuf *m = env.mbuf;
+ uint16_t data_len = rte_pktmbuf_pkt_len(m);
+ uint16_t total_len = data_len + env.digest_len;
+ uint8_t *src, *dst, *wb_data;
+
+ /* in case val is reused for MCT test, try to free the buffer first */
+ if (val->val) {
+ free(val->val);
+ val->val = NULL;
+ }
+
+ wb_data = dst = calloc(1, total_len);
+ if (!dst) {
+ RTE_LOG(ERR, USER1, "Error %i: Not enough memory\n", -ENOMEM);
+ return -ENOMEM;
+ }
+
+ while (m && data_len) {
+ uint16_t seg_len = RTE_MIN(rte_pktmbuf_data_len(m), data_len);
+
+ src = rte_pktmbuf_mtod(m, uint8_t *);
+ memcpy(dst, src, seg_len);
+ m = m->next;
+ data_len -= seg_len;
+ dst += seg_len;
+ }
+
+ if (data_len) {
+ RTE_LOG(ERR, USER1, "Error -1: write back data\n");
+ free(wb_data);
+ return -1;
+ }
+
+ if (env.digest)
+ memcpy(dst, env.digest, env.digest_len);
+
+ val->val = wb_data;
+ val->len = total_len;
+
+ return 0;
+}
+
+static int
+fips_run_test(void)
+{
+ struct rte_crypto_sym_xform xform = {0};
+ uint16_t n_deqd;
+ int ret;
+
+ ret = test_ops.prepare_xform(&xform);
+ if (ret < 0)
+ return ret;
+
+ env.sess = rte_cryptodev_sym_session_create(env.sess_mpool);
+ if (!env.sess)
+ return -ENOMEM;
+
+ ret = rte_cryptodev_sym_session_init(env.dev_id,
+ env.sess, &xform, env.sess_priv_mpool);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1, "Error %i: Init session\n",
+ ret);
+ goto exit;
+ }
+
+ ret = test_ops.prepare_op();
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
+ ret);
+ goto exit;
+ }
+
+ if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) {
+ RTE_LOG(ERR, USER1, "Error: Failed enqueue\n");
+ ret = -1;
+ goto exit;
+ }
+
+ do {
+ struct rte_crypto_op *deqd_op;
+
+ n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
+ 1);
+ } while (n_deqd == 0);
+
+ vec.status = env.op->status;
+
+exit:
+ rte_cryptodev_sym_session_clear(env.dev_id, env.sess);
+ rte_cryptodev_sym_session_free(env.sess);
+ env.sess = NULL;
+
+ return ret;
+}
+
+static int
+fips_generic_test(void)
+{
+ struct fips_val val = {NULL, 0};
+ int ret;