diff --git a/drivers/crypto/cpt/cpt_pmd_cryptodev.c b/drivers/crypto/cpt/cpt_pmd_cryptodev.c
index 3961ec8..939f31b 100644
--- a/drivers/crypto/cpt/cpt_pmd_cryptodev.c
+++ b/drivers/crypto/cpt/cpt_pmd_cryptodev.c
@@ -62,9 +62,9 @@
 	.queue_pair_count = NULL,
 
 	/* Crypto related operations */
-	.session_get_size = NULL,
-	.session_configure = NULL,
-	.session_clear = NULL
+	.session_get_size = cpt_pmd_get_session_size,
+	.session_configure = cpt_pmd_session_cfg,
+	.session_clear = cpt_pmd_session_clear
 };
 
 static int init_global_resources(void)
diff --git a/drivers/crypto/cpt/cpt_pmd_ops.c b/drivers/crypto/cpt/cpt_pmd_ops.c
index 1c60191..37808ce 100644
--- a/drivers/crypto/cpt/cpt_pmd_ops.c
+++ b/drivers/crypto/cpt/cpt_pmd_ops.c
@@ -605,3 +605,473 @@ void cpt_pmd_stats_reset(struct rte_cryptodev *dev __rte_unused)
 
 	return 0;
 }
+
+unsigned int
+cpt_pmd_get_session_size(struct rte_cryptodev *dev __rte_unused)
+{
+	return (sizeof(struct cpt_sess_misc) +
+		RTE_ALIGN_CEIL(cpt_fc_get_ctx_len(), 8));
+}
+
+static int
+fill_sess_aead(cpt_instance_t *instance, struct rte_crypto_sym_xform *xform,
+		 struct cpt_sess_misc *sess)
+{
+	struct rte_crypto_aead_xform *aead_form;
+	cipher_type_t enc_type = 0; /* NULL Cipher type */
+	auth_type_t auth_type = 0; /* NULL Auth type */
+	uint32_t cipher_key_len = 0;
+	uint8_t zsk_flag = 0, aes_gcm = 0;
+	aead_form = &xform->aead;
+	if (aead_form->op == RTE_CRYPTO_AEAD_OP_ENCRYPT &&
+	   aead_form->algo == RTE_CRYPTO_AEAD_AES_GCM) {
+		sess->cpt_op |= CSP_OP_CIPHER_ENCRYPT;
+		sess->cpt_op |= CSP_OP_AUTH_GENERATE;
+	} else if (aead_form->op == RTE_CRYPTO_AEAD_OP_DECRYPT &&
+		aead_form->algo == RTE_CRYPTO_AEAD_AES_GCM) {
+		sess->cpt_op |= CSP_OP_CIPHER_DECRYPT;
+		sess->cpt_op |= CSP_OP_AUTH_VERIFY;
+	} else {
+		PMD_DRV_LOG(ERR, "Unknown cipher operation\n");
+		return -1;
+	}
+	if (aead_form->key.length < cipher_key_len) {
+		PMD_DRV_LOG(ERR, "Invalid cipher params keylen %lu\n",
+		(unsigned int long)aead_form->key.length);
+		return -1;
+	}
+	switch (aead_form->algo) {
+	case RTE_CRYPTO_AEAD_AES_GCM:
+		enc_type = AES_GCM;
+		cipher_key_len = 16;
+		aes_gcm = 1;
+		break;
+	case RTE_CRYPTO_AEAD_AES_CCM:
+		PMD_DRV_LOG(ERR, "Crypto: Unsupported cipher alg %u",
+			    aead_form->algo);
+		return -1;
+	default:
+		PMD_DRV_LOG(ERR, "Crypto: Undefined cipher algo %u specified",
+			    aead_form->algo);
+		return -1;
+	}
+	sess->zsk_flag = zsk_flag;
+	sess->aes_gcm = aes_gcm;
+	sess->mac_len = aead_form->digest_length;
+	sess->iv_offset = aead_form->iv.offset;
+	sess->iv_length = aead_form->iv.length;
+	sess->aad_length = aead_form->aad_length;
+	cpt_fc_ciph_set_key(instance,
+		(void *)((uint8_t *)sess + sizeof(struct cpt_sess_misc)),
+			enc_type,
+			aead_form->key.data,
+			aead_form->key.length,
+			NULL);
+
+	cpt_fc_auth_set_key(instance,
+		(void *)((uint8_t *)sess + sizeof(struct cpt_sess_misc)),
+		auth_type,
+		NULL,
+		0,
+		aead_form->digest_length);
+
+	return 0;
+}
+static int
+fill_sess_cipher(cpt_instance_t *instance, struct rte_crypto_sym_xform *xform,
+		 struct cpt_sess_misc *sess)
+{
+	struct rte_crypto_cipher_xform *c_form;
+	cipher_type_t enc_type = 0; /* NULL Cipher type */
+	uint32_t cipher_key_len = 0;
+	uint8_t zsk_flag = 0, aes_gcm = 0, aes_ctr = 0;
+
+	if (xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER)
+		return -1;
+
+	c_form = &xform->cipher;
+
+	if (c_form->op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
+		sess->cpt_op |= CSP_OP_CIPHER_ENCRYPT;
+	else if (c_form->op == RTE_CRYPTO_CIPHER_OP_DECRYPT)
+		sess->cpt_op |= CSP_OP_CIPHER_DECRYPT;
+	else {
+		PMD_DRV_LOG(ERR, "Unknown cipher operation\n");
+		return -1;
+	}
+
+	switch (c_form->algo) {
+	case RTE_CRYPTO_CIPHER_AES_CBC:
+		enc_type = AES_CBC;
+		cipher_key_len = 16;
+		sess->dir_dma_supp |= CSP_DDMA_ENC;
+		break;
+	case RTE_CRYPTO_CIPHER_3DES_CBC:
+		enc_type = DES3_CBC;
+		cipher_key_len = 24;
+		break;
+	case RTE_CRYPTO_CIPHER_AES_CTR:
+		enc_type = AES_CTR;
+		cipher_key_len = 16;
+		aes_ctr = 1;
+		break;
+	case RTE_CRYPTO_CIPHER_NULL:
+		enc_type = 0;
+		break;
+	case RTE_CRYPTO_CIPHER_KASUMI_F8:
+		enc_type = KASUMI_F8_ECB;
+		cipher_key_len = 16;
+		zsk_flag = K_F8;
+		break;
+	case RTE_CRYPTO_CIPHER_SNOW3G_UEA2:
+		enc_type = SNOW3G_UEA2;
+		cipher_key_len = 16;
+		zsk_flag = ZS_EA;
+		break;
+	case RTE_CRYPTO_CIPHER_ZUC_EEA3:
+		enc_type = ZUC_EEA3;
+		cipher_key_len = 16;
+		zsk_flag = ZS_EA;
+		break;
+	case RTE_CRYPTO_CIPHER_AES_XTS:
+		enc_type = AES_XTS;
+		cipher_key_len = 16;
+		break;
+	case RTE_CRYPTO_CIPHER_3DES_ECB:
+		enc_type = DES3_ECB;
+		cipher_key_len = 24;
+		break;
+	case RTE_CRYPTO_CIPHER_AES_ECB:
+		enc_type = AES_ECB;
+		cipher_key_len = 16;
+		break;
+	case RTE_CRYPTO_CIPHER_3DES_CTR:
+	case RTE_CRYPTO_CIPHER_AES_F8:
+	case RTE_CRYPTO_CIPHER_ARC4:
+		PMD_DRV_LOG(ERR, "Crypto: Unsupported cipher alg %u",
+			    c_form->algo);
+		return -1;
+	default:
+		PMD_DRV_LOG(ERR, "Crypto: Undefined cipher algo %u specified",
+			    c_form->algo);
+		return -1;
+	}
+
+	if (c_form->key.length < cipher_key_len) {
+		PMD_DRV_LOG(ERR, "Invalid cipher params keylen %lu\n",
+			    (unsigned long) c_form->key.length);
+		return -1;
+	}
+
+	sess->zsk_flag = zsk_flag;
+	sess->aes_gcm = aes_gcm;
+	sess->aes_ctr = aes_ctr;
+	sess->iv_offset = c_form->iv.offset;
+	sess->iv_length = c_form->iv.length;
+	cpt_fc_ciph_set_key(instance,
+			    SESS_PRIV(sess),
+			    enc_type,
+			    c_form->key.data,
+			    c_form->key.length,
+			    NULL);
+
+	return 0;
+}
+
+static int
+fill_sess_auth(cpt_instance_t *instance, struct rte_crypto_sym_xform *xform,
+	       struct cpt_sess_misc *sess)
+{
+	struct rte_crypto_auth_xform *a_form;
+	auth_type_t auth_type = 0; /* NULL Auth type */
+	uint8_t zsk_flag = 0, aes_gcm = 0;
+
+	if (xform->type != RTE_CRYPTO_SYM_XFORM_AUTH)
+		goto error_out;
+
+	a_form = &xform->auth;
+
+	if (a_form->op == RTE_CRYPTO_AUTH_OP_VERIFY)
+		sess->cpt_op |= CSP_OP_AUTH_VERIFY;
+	else if (a_form->op == RTE_CRYPTO_AUTH_OP_GENERATE)
+		sess->cpt_op |= CSP_OP_AUTH_GENERATE;
+	else {
+		PMD_DRV_LOG(ERR, "Unknown auth operation\n");
+		return -1;
+	}
+
+	if (a_form->key.length > 64) {
+		PMD_DRV_LOG(ERR, "Auth key length is big\n");
+		return -1;
+	}
+
+	switch (a_form->algo) {
+	case RTE_CRYPTO_AUTH_SHA1_HMAC:
+		sess->dir_dma_supp |= CSP_DDMA_AUTH;
+		/* Fall through */
+	case RTE_CRYPTO_AUTH_SHA1:
+		auth_type = SHA1_TYPE;
+		break;
+	case RTE_CRYPTO_AUTH_SHA256_HMAC:
+	case RTE_CRYPTO_AUTH_SHA256:
+		auth_type = SHA2_SHA256;
+		break;
+	case RTE_CRYPTO_AUTH_SHA512_HMAC:
+	case RTE_CRYPTO_AUTH_SHA512:
+		auth_type = SHA2_SHA512;
+		break;
+	case RTE_CRYPTO_AUTH_AES_GMAC:
+		auth_type = GMAC_TYPE;
+		aes_gcm = 1;
+		break;
+	case RTE_CRYPTO_AUTH_SHA224_HMAC:
+	case RTE_CRYPTO_AUTH_SHA224:
+		auth_type = SHA2_SHA224;
+		break;
+	case RTE_CRYPTO_AUTH_SHA384_HMAC:
+	case RTE_CRYPTO_AUTH_SHA384:
+		auth_type = SHA2_SHA384;
+		break;
+	case RTE_CRYPTO_AUTH_MD5_HMAC:
+	case RTE_CRYPTO_AUTH_MD5:
+		auth_type = MD5_TYPE;
+		break;
+	case RTE_CRYPTO_AUTH_KASUMI_F9:
+		auth_type = KASUMI_F9_ECB;
+		/*
+		 * Indicate that direction needs to be taken out
+		 * from end of src
+		 */
+		zsk_flag = K_F9;
+		break;
+	case RTE_CRYPTO_AUTH_SNOW3G_UIA2:
+		auth_type = SNOW3G_UIA2;
+		zsk_flag = ZS_IA;
+		break;
+	case RTE_CRYPTO_AUTH_ZUC_EIA3:
+		auth_type = ZUC_EIA3;
+		zsk_flag = ZS_IA;
+		break;
+	case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
+	case RTE_CRYPTO_AUTH_AES_CMAC:
+	case RTE_CRYPTO_AUTH_AES_CBC_MAC:
+	case RTE_CRYPTO_AUTH_NULL:
+		PMD_DRV_LOG(ERR, "Crypto: Unsupported hash alg %u",
+			    a_form->algo);
+		goto error_out;
+	default:
+		PMD_DRV_LOG(ERR, "Crypto: Undefined Hash algo %u specified",
+			    a_form->algo);
+		goto error_out;
+	}
+
+	sess->zsk_flag = zsk_flag;
+	sess->aes_gcm = aes_gcm;
+	sess->mac_len = a_form->digest_length;
+	if (zsk_flag) {
+		sess->auth_iv_offset = a_form->iv.offset;
+		sess->auth_iv_length = a_form->iv.length;
+	}
+	cpt_fc_auth_set_key(instance,
+			    SESS_PRIV(sess),
+			    auth_type,
+			    a_form->key.data,
+			    a_form->key.length,
+			    a_form->digest_length);
+
+	return 0;
+
+error_out:
+	return -1;
+}
+static int
+fill_sess_gmac(cpt_instance_t *instance, struct rte_crypto_sym_xform *xform,
+		 struct cpt_sess_misc *sess)
+{
+	struct rte_crypto_auth_xform *a_form;
+	cipher_type_t enc_type = 0; /* NULL Cipher type */
+	auth_type_t auth_type = 0; /* NULL Auth type */
+	uint8_t zsk_flag = 0, aes_gcm = 0;
+
+	if (xform->type != RTE_CRYPTO_SYM_XFORM_AUTH)
+		return -1;
+
+	a_form = &xform->auth;
+
+	if (a_form->op == RTE_CRYPTO_AUTH_OP_GENERATE)
+		sess->cpt_op |= CSP_OP_ENCODE;
+	else if (a_form->op == RTE_CRYPTO_AUTH_OP_VERIFY)
+		sess->cpt_op |= CSP_OP_DECODE;
+	else {
+		PMD_DRV_LOG(ERR, "Unknown auth operation\n");
+		return -1;
+	}
+
+	switch (a_form->algo) {
+	case RTE_CRYPTO_AUTH_AES_GMAC:
+		enc_type = AES_GCM;
+		auth_type = GMAC_TYPE;
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Crypto: Undefined cipher algo %u specified",
+			    a_form->algo);
+		return -1;
+	}
+
+	sess->zsk_flag = zsk_flag;
+	sess->aes_gcm = aes_gcm;
+	sess->is_gmac = 1;
+	sess->iv_offset = a_form->iv.offset;
+	sess->iv_length = a_form->iv.length;
+	sess->mac_len = a_form->digest_length;
+	cpt_fc_ciph_set_key(instance,
+		(void *)((uint8_t *)sess + sizeof(struct cpt_sess_misc)),
+			enc_type,
+			a_form->key.data,
+			a_form->key.length,
+			NULL);
+	cpt_fc_auth_set_key(instance,
+		(void *)((uint8_t *)sess + sizeof(struct cpt_sess_misc)),
+		auth_type,
+		NULL,
+		0,
+		a_form->digest_length);
+
+	return 0;
+}
+
+static void
+cpt_pmd_session_init(struct rte_mempool *mp __rte_unused, void *sym_sess,
+		 uint8_t driver_id)
+{
+	struct rte_cryptodev_sym_session *sess = sym_sess;
+	struct cpt_sess_misc *cpt_sess =
+	  (struct cpt_sess_misc *) get_session_private_data(sess, driver_id);
+
+	PMD_INIT_FUNC_TRACE();
+	cpt_sess->ctx_dma_addr = rte_mempool_virt2iova(cpt_sess) +
+			sizeof(struct cpt_sess_misc);
+}
+
+
+int cpt_pmd_session_cfg(struct rte_cryptodev *dev,
+		    struct rte_crypto_sym_xform *xform,
+		    struct rte_cryptodev_sym_session *sess,
+		    struct rte_mempool *mempool)
+{
+	struct rte_crypto_sym_xform *chain;
+	void *sess_private_data;
+
+	PMD_INIT_FUNC_TRACE();
+
+	/*
+	 * Microcode only supports the following combination.
+	 * Encryption followed by authentication
+	 * Authentication followed by decryption
+	 * Also zuc, kasumi and snow3g are not supported in
+	 * aead mode(ie. cipher+auth), but only cipher or auth.
+	 */
+	if (xform->next) {
+		if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
+			if ((xform->auth.algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2) ||
+			    (xform->auth.algo == RTE_CRYPTO_AUTH_ZUC_EIA3) ||
+			    (xform->auth.algo == RTE_CRYPTO_AUTH_KASUMI_F9)) {
+				PMD_DRV_LOG(ERR, "Requested auth algorithm in "
+				 "combination with cipher unsupported\n");
+				goto err;
+			}
+			if ((xform->next->type ==
+			     RTE_CRYPTO_SYM_XFORM_CIPHER) &&
+			    (xform->next->cipher.op ==
+			     RTE_CRYPTO_CIPHER_OP_ENCRYPT)) {
+				PMD_DRV_LOG(ERR, "Unsupported combination by "
+				 "microcode\n");
+				goto err;
+				/* Unsupported as of now by microcode */
+			}
+		}
+		if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+			if ((xform->cipher.algo ==
+			     RTE_CRYPTO_CIPHER_SNOW3G_UEA2) ||
+			    (xform->cipher.algo ==
+			     RTE_CRYPTO_CIPHER_ZUC_EEA3) ||
+			    (xform->cipher.algo ==
+			     RTE_CRYPTO_CIPHER_KASUMI_F8)) {
+				PMD_DRV_LOG(ERR, "Requested cipher algorithm "
+				 "in combination with auth unsupported\n");
+				goto err;
+			}
+			if ((xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH) &&
+			(xform->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT)) {
+				/* For GMAC auth there is no cipher operation */
+				if ((xform->aead.algo !=
+				     RTE_CRYPTO_AEAD_AES_GCM) ||
+				    (xform->next->auth.algo !=
+				     RTE_CRYPTO_AUTH_AES_GMAC)) {
+					PMD_DRV_LOG(ERR, "Unsupported "
+					 "combination by microcode\n");
+					goto err;
+					/* Unsupported as of now by microcode */
+				}
+			}
+		}
+	}
+
+	if (unlikely(sess == NULL)) {
+		PMD_DRV_LOG(ERR, "invalid session struct");
+		return -EINVAL;
+	}
+
+	if (rte_mempool_get(mempool, &sess_private_data)) {
+		PMD_DRV_LOG(ERR, "Could not allocate sess_private_data\n");
+		return -ENOMEM;
+	}
+
+	chain = xform;
+	((struct cpt_sess_misc *) sess_private_data)->dir_dma_supp = 0;
+	/* TODO: Need to restrict this loop to 2 chain elements? */
+	while (chain) {
+		if (chain->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
+			if (fill_sess_aead(NULL, chain, sess_private_data))
+				goto err;
+		} else {
+		if (chain->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+			if (fill_sess_cipher(NULL, chain, sess_private_data))
+				goto err;
+		} else if (chain->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
+			if (chain->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+				if (fill_sess_gmac(NULL, chain,
+				    sess_private_data))
+					goto err;
+			} else {
+			if (fill_sess_auth(NULL, chain, sess_private_data))
+				goto err;
+			}
+		}
+		}
+		chain = chain->next;
+	}
+	set_session_private_data(sess, dev->driver_id, sess_private_data);
+	cpt_pmd_session_init(NULL, sess, dev->driver_id);
+	return 0;
+
+err:
+	/* TODO: rte_mempool_put(); */
+	return -EPERM;
+}
+
+void
+cpt_pmd_session_clear(struct rte_cryptodev *dev,
+		  struct rte_cryptodev_sym_session *sess)
+{
+	void *session_private = get_session_private_data(sess, dev->driver_id);
+
+	PMD_INIT_FUNC_TRACE();
+	if (session_private) {
+		memset(session_private, 0, cpt_pmd_get_session_size(dev));
+		struct rte_mempool *sess_mp =
+		   rte_mempool_from_obj(session_private);
+		set_session_private_data(sess, dev->driver_id, NULL);
+		rte_mempool_put(sess_mp, session_private);
+	}
+}
diff --git a/drivers/crypto/cpt/cpt_pmd_ops.h b/drivers/crypto/cpt/cpt_pmd_ops.h
index db2024b..314b2b1 100644
--- a/drivers/crypto/cpt/cpt_pmd_ops.h
+++ b/drivers/crypto/cpt/cpt_pmd_ops.h
@@ -72,4 +72,15 @@ void cpt_pmd_stats_get(struct rte_cryptodev *dev,
 
 void cpt_pmd_stats_reset(struct rte_cryptodev *dev);
 
+unsigned int
+cpt_pmd_get_session_size(struct rte_cryptodev *dev);
+
+int cpt_pmd_session_cfg(struct rte_cryptodev *dev,
+		    struct rte_crypto_sym_xform *xform,
+		    struct rte_cryptodev_sym_session *sess,
+		    struct rte_mempool *mempool);
+
+void
+cpt_pmd_session_clear(struct rte_cryptodev *dev,
+		  struct rte_cryptodev_sym_session *sess);
 #endif
