From: Ragothaman Jayaraman <ragothaman.jayara...@cavium.com>

This patch adds the session callbacks functions. The cipher
keys, auth keys and aead keys are set during the session configure.

Signed-off-by: Ankur Dwivedi <ankur.dwiv...@cavium.com>
Signed-off-by: Murthy NSSR <nidadavolu.mur...@cavium.com>
Signed-off-by: Nithin Dabilpuram <nithin.dabilpu...@cavium.com>
Signed-off-by: Ragothaman Jayaraman <ragothaman.jayara...@cavium.com>
Signed-off-by: Srisivasubramanian Srinivasan 
<srisivasubramanian.sriniva...@cavium.com>
---
 drivers/crypto/cpt/cpt_pmd_cryptodev.c |   6 +-
 drivers/crypto/cpt/cpt_pmd_ops.c       | 470 +++++++++++++++++++++++++++++++++
 drivers/crypto/cpt/cpt_pmd_ops.h       |  11 +
 3 files changed, 484 insertions(+), 3 deletions(-)

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
-- 
1.9.3

Reply via email to