[generic-2.4] add OCF 20100325 support to brcm-2.4
[openwrt/svn-archive/archive.git] / target / linux / generic-2.4 / files / crypto / ocf / ep80579 / icp_asym.c
diff --git a/target/linux/generic-2.4/files/crypto/ocf/ep80579/icp_asym.c b/target/linux/generic-2.4/files/crypto/ocf/ep80579/icp_asym.c
new file mode 100644 (file)
index 0000000..d2641c5
--- /dev/null
@@ -0,0 +1,1334 @@
+/***************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or 
+ *   redistributing this file, you may do so under either license.
+ * 
+ *   GPL LICENSE SUMMARY
+ * 
+ *   Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+ * 
+ *   This program is free software; you can redistribute it and/or modify 
+ *   it under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ * 
+ *   This program is distributed in the hope that it will be useful, but 
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+ *   General Public License for more details.
+ * 
+ *   You should have received a copy of the GNU General Public License 
+ *   along with this program; if not, write to the Free Software 
+ *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *   The full GNU General Public License is included in this distribution 
+ *   in the file called LICENSE.GPL.
+ * 
+ *   Contact Information:
+ *   Intel Corporation
+ * 
+ *   BSD LICENSE 
+ * 
+ *   Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ * 
+ *   Redistribution and use in source and binary forms, with or without 
+ *   modification, are permitted provided that the following conditions 
+ *   are met:
+ * 
+ *     * Redistributions of source code must retain the above copyright 
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright 
+ *       notice, this list of conditions and the following disclaimer in 
+ *       the documentation and/or other materials provided with the 
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its 
+ *       contributors may be used to endorse or promote products derived 
+ *       from this software without specific prior written permission.
+ * 
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * 
+ *  version: Security.L.1.0.2-229
+ *
+ ***************************************************************************/
+
+#include "icp_ocf.h"
+
+/*The following define values (containing the word 'INDEX') are used to find
+the index of each input buffer of the crypto_kop struct (see OCF cryptodev.h).
+These values were found through analysis of the OCF OpenSSL patch. If the
+calling program uses different input buffer positions, these defines will have
+to be changed.*/
+
+/*DIFFIE HELLMAN buffer index values*/
+#define ICP_DH_KRP_PARAM_PRIME_INDEX                            (0)
+#define ICP_DH_KRP_PARAM_BASE_INDEX                             (1)
+#define ICP_DH_KRP_PARAM_PRIVATE_VALUE_INDEX                    (2)
+#define ICP_DH_KRP_PARAM_RESULT_INDEX                           (3)
+
+/*MOD EXP buffer index values*/
+#define ICP_MOD_EXP_KRP_PARAM_BASE_INDEX                        (0)
+#define ICP_MOD_EXP_KRP_PARAM_EXPONENT_INDEX                    (1)
+#define ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX                     (2)
+#define ICP_MOD_EXP_KRP_PARAM_RESULT_INDEX                      (3)
+
+/*MOD EXP CRT buffer index values*/
+#define ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_P_INDEX                 (0)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_Q_INDEX                 (1)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_I_INDEX                       (2)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DP_INDEX             (3)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DQ_INDEX             (4)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_COEFF_QINV_INDEX              (5)
+#define ICP_MOD_EXP_CRT_KRP_PARAM_RESULT_INDEX                  (6)
+
+/*DSA sign buffer index values*/
+#define ICP_DSA_SIGN_KRP_PARAM_DGST_INDEX                       (0)
+#define ICP_DSA_SIGN_KRP_PARAM_PRIME_P_INDEX                    (1)
+#define ICP_DSA_SIGN_KRP_PARAM_PRIME_Q_INDEX                    (2)
+#define ICP_DSA_SIGN_KRP_PARAM_G_INDEX                          (3)
+#define ICP_DSA_SIGN_KRP_PARAM_X_INDEX                          (4)
+#define ICP_DSA_SIGN_KRP_PARAM_R_RESULT_INDEX                   (5)
+#define ICP_DSA_SIGN_KRP_PARAM_S_RESULT_INDEX                   (6)
+
+/*DSA verify buffer index values*/
+#define ICP_DSA_VERIFY_KRP_PARAM_DGST_INDEX                     (0)
+#define ICP_DSA_VERIFY_KRP_PARAM_PRIME_P_INDEX                  (1)
+#define ICP_DSA_VERIFY_KRP_PARAM_PRIME_Q_INDEX                  (2)
+#define ICP_DSA_VERIFY_KRP_PARAM_G_INDEX                        (3)
+#define ICP_DSA_VERIFY_KRP_PARAM_PUBKEY_INDEX                   (4)
+#define ICP_DSA_VERIFY_KRP_PARAM_SIG_R_INDEX                    (5)
+#define ICP_DSA_VERIFY_KRP_PARAM_SIG_S_INDEX                    (6)
+
+/*DSA sign prime Q vs random number K size check values*/
+#define DONT_RUN_LESS_THAN_CHECK                                (0)
+#define FAIL_A_IS_GREATER_THAN_B                                (1)
+#define FAIL_A_IS_EQUAL_TO_B                                    (1)
+#define SUCCESS_A_IS_LESS_THAN_B                                (0)
+#define DSA_SIGN_RAND_GEN_VAL_CHECK_MAX_ITERATIONS              (500)
+
+/* We need to set a cryptokp success value just in case it is set or allocated
+   and not set to zero outside of this module */
+#define CRYPTO_OP_SUCCESS                                       (0)
+
+/*Function to compute Diffie Hellman (DH) phase 1 or phase 2 key values*/
+static int icp_ocfDrvDHComputeKey(struct cryptkop *krp);
+
+/*Function to compute a Modular Exponentiation (Mod Exp)*/
+static int icp_ocfDrvModExp(struct cryptkop *krp);
+
+/*Function to compute a Mod Exp using the Chinease Remainder Theorem*/
+static int icp_ocfDrvModExpCRT(struct cryptkop *krp);
+
+/*Helper function to compute whether the first big number argument is less than
+ the second big number argument */
+static int
+icp_ocfDrvCheckALessThanB(CpaFlatBuffer * pK, CpaFlatBuffer * pQ, int *doCheck);
+
+/*Function to sign an input with DSA R and S keys*/
+static int icp_ocfDrvDsaSign(struct cryptkop *krp);
+
+/*Function to Verify a DSA buffer signature*/
+static int icp_ocfDrvDsaVerify(struct cryptkop *krp);
+
+/*Callback function for DH operation*/
+static void
+icp_ocfDrvDhP1CallBack(void *callbackTag,
+                      CpaStatus status,
+                      void *pOpData, CpaFlatBuffer * pLocalOctetStringPV);
+
+/*Callback function for ME operation*/
+static void
+icp_ocfDrvModExpCallBack(void *callbackTag,
+                        CpaStatus status,
+                        void *pOpData, CpaFlatBuffer * pResult);
+
+/*Callback function for ME CRT operation*/
+static void
+icp_ocfDrvModExpCRTCallBack(void *callbackTag,
+                           CpaStatus status,
+                           void *pOpData, CpaFlatBuffer * pOutputData);
+
+/*Callback function for DSA sign operation*/
+static void
+icp_ocfDrvDsaRSSignCallBack(void *callbackTag,
+                           CpaStatus status,
+                           void *pOpData,
+                           CpaBoolean protocolStatus,
+                           CpaFlatBuffer * pR, CpaFlatBuffer * pS);
+
+/*Callback function for DSA Verify operation*/
+static void
+icp_ocfDrvDsaVerifyCallBack(void *callbackTag,
+                           CpaStatus status,
+                           void *pOpData, CpaBoolean verifyStatus);
+
+/* Name        : icp_ocfDrvPkeProcess
+ *
+ * Description : This function will choose which PKE process to follow
+ * based on the input arguments
+ */
+int icp_ocfDrvPkeProcess(icp_device_t dev, struct cryptkop *krp, int hint)
+{
+       CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+
+       if (NULL == krp) {
+               DPRINTK("%s(): Invalid input parameters, cryptkop = %p\n",
+                       __FUNCTION__, krp);
+               return EINVAL;
+       }
+
+       if (CPA_TRUE == icp_atomic_read(&icp_ocfDrvIsExiting)) {
+               krp->krp_status = ECANCELED;
+               return ECANCELED;
+       }
+
+       switch (krp->krp_op) {
+       case CRK_DH_COMPUTE_KEY:
+               DPRINTK("%s() doing DH_COMPUTE_KEY\n", __FUNCTION__);
+               lacStatus = icp_ocfDrvDHComputeKey(krp);
+               if (CPA_STATUS_SUCCESS != lacStatus) {
+                       EPRINTK("%s(): icp_ocfDrvDHComputeKey failed "
+                               "(%d).\n", __FUNCTION__, lacStatus);
+                       krp->krp_status = ECANCELED;
+                       return ECANCELED;
+               }
+
+               break;
+
+       case CRK_MOD_EXP:
+               DPRINTK("%s() doing MOD_EXP \n", __FUNCTION__);
+               lacStatus = icp_ocfDrvModExp(krp);
+               if (CPA_STATUS_SUCCESS != lacStatus) {
+                       EPRINTK("%s(): icp_ocfDrvModExp failed (%d).\n",
+                               __FUNCTION__, lacStatus);
+                       krp->krp_status = ECANCELED;
+                       return ECANCELED;
+               }
+
+               break;
+
+       case CRK_MOD_EXP_CRT:
+               DPRINTK("%s() doing MOD_EXP_CRT \n", __FUNCTION__);
+               lacStatus = icp_ocfDrvModExpCRT(krp);
+               if (CPA_STATUS_SUCCESS != lacStatus) {
+                       EPRINTK("%s(): icp_ocfDrvModExpCRT "
+                               "failed (%d).\n", __FUNCTION__, lacStatus);
+                       krp->krp_status = ECANCELED;
+                       return ECANCELED;
+               }
+
+               break;
+
+       case CRK_DSA_SIGN:
+               DPRINTK("%s() doing DSA_SIGN \n", __FUNCTION__);
+               lacStatus = icp_ocfDrvDsaSign(krp);
+               if (CPA_STATUS_SUCCESS != lacStatus) {
+                       EPRINTK("%s(): icp_ocfDrvDsaSign "
+                               "failed (%d).\n", __FUNCTION__, lacStatus);
+                       krp->krp_status = ECANCELED;
+                       return ECANCELED;
+               }
+
+               break;
+
+       case CRK_DSA_VERIFY:
+               DPRINTK("%s() doing DSA_VERIFY \n", __FUNCTION__);
+               lacStatus = icp_ocfDrvDsaVerify(krp);
+               if (CPA_STATUS_SUCCESS != lacStatus) {
+                       EPRINTK("%s(): icp_ocfDrvDsaVerify "
+                               "failed (%d).\n", __FUNCTION__, lacStatus);
+                       krp->krp_status = ECANCELED;
+                       return ECANCELED;
+               }
+
+               break;
+
+       default:
+               EPRINTK("%s(): Asymettric function not "
+                       "supported (%d).\n", __FUNCTION__, krp->krp_op);
+               krp->krp_status = EOPNOTSUPP;
+               return EOPNOTSUPP;
+       }
+
+       return ICP_OCF_DRV_STATUS_SUCCESS;
+}
+
+/* Name        : icp_ocfDrvSwapBytes
+ *
+ * Description : This function is used to swap the byte order of a buffer.
+ * It has been seen that in general we are passed little endian byte order
+ * buffers, but LAC only accepts big endian byte order buffers.
+ */
+static void inline icp_ocfDrvSwapBytes(u_int8_t * num, u_int32_t buff_len_bytes)
+{
+
+       int i;
+       u_int8_t *end_ptr;
+       u_int8_t hold_val;
+
+       end_ptr = num + (buff_len_bytes - 1);
+       buff_len_bytes = buff_len_bytes >> 1;
+       for (i = 0; i < buff_len_bytes; i++) {
+               hold_val = *num;
+               *num = *end_ptr;
+               num++;
+               *end_ptr = hold_val;
+               end_ptr--;
+       }
+}
+
+/* Name        : icp_ocfDrvDHComputeKey
+ *
+ * Description : This function will map Diffie Hellman calls from OCF
+ * to the LAC API. OCF uses this function for Diffie Hellman Phase1 and
+ * Phase2. LAC has a separate Diffie Hellman Phase2 call, however both phases
+ * break down to a modular exponentiation.
+ */
+static int icp_ocfDrvDHComputeKey(struct cryptkop *krp)
+{
+       CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+       void *callbackTag = NULL;
+       CpaCyDhPhase1KeyGenOpData *pPhase1OpData = NULL;
+       CpaFlatBuffer *pLocalOctetStringPV = NULL;
+       uint32_t dh_prime_len_bytes = 0, dh_prime_len_bits = 0;
+
+       /* Input checks - check prime is a multiple of 8 bits to allow for
+          allocation later */
+       dh_prime_len_bits =
+           (krp->krp_param[ICP_DH_KRP_PARAM_PRIME_INDEX].crp_nbits);
+
+       /* LAC can reject prime lengths based on prime key sizes, we just
+          need to make sure we can allocate space for the base and
+          exponent buffers correctly */
+       if ((dh_prime_len_bits % NUM_BITS_IN_BYTE) != 0) {
+               APRINTK("%s(): Warning Prime number buffer size is not a "
+                       "multiple of 8 bits\n", __FUNCTION__);
+       }
+
+       /* Result storage space should be the same size as the prime as this
+          value can take up the same amount of storage space */
+       if (dh_prime_len_bits !=
+           krp->krp_param[ICP_DH_KRP_PARAM_RESULT_INDEX].crp_nbits) {
+               DPRINTK("%s(): Return Buffer must be the same size "
+                       "as the Prime buffer\n", __FUNCTION__);
+               krp->krp_status = EINVAL;
+               return EINVAL;
+       }
+       /* Switch to size in bytes */
+       BITS_TO_BYTES(dh_prime_len_bytes, dh_prime_len_bits);
+
+       callbackTag = krp;
+
+/*All allocations are set to ICP_M_NOWAIT due to the possibility of getting
+called in interrupt context*/
+       pPhase1OpData = icp_kmem_cache_zalloc(drvDH_zone, ICP_M_NOWAIT);
+       if (NULL == pPhase1OpData) {
+               APRINTK("%s():Failed to get memory for key gen data\n",
+                       __FUNCTION__);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       pLocalOctetStringPV =
+           icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
+       if (NULL == pLocalOctetStringPV) {
+               APRINTK("%s():Failed to get memory for pLocalOctetStringPV\n",
+                       __FUNCTION__);
+               ICP_CACHE_FREE(drvDH_zone, pPhase1OpData);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       /* Link parameters */
+       pPhase1OpData->primeP.pData =
+           krp->krp_param[ICP_DH_KRP_PARAM_PRIME_INDEX].crp_p;
+
+       pPhase1OpData->primeP.dataLenInBytes = dh_prime_len_bytes;
+
+       icp_ocfDrvSwapBytes(pPhase1OpData->primeP.pData, dh_prime_len_bytes);
+
+       pPhase1OpData->baseG.pData =
+           krp->krp_param[ICP_DH_KRP_PARAM_BASE_INDEX].crp_p;
+
+       BITS_TO_BYTES(pPhase1OpData->baseG.dataLenInBytes,
+                     krp->krp_param[ICP_DH_KRP_PARAM_BASE_INDEX].crp_nbits);
+
+       icp_ocfDrvSwapBytes(pPhase1OpData->baseG.pData,
+                           pPhase1OpData->baseG.dataLenInBytes);
+
+       pPhase1OpData->privateValueX.pData =
+           krp->krp_param[ICP_DH_KRP_PARAM_PRIVATE_VALUE_INDEX].crp_p;
+
+       BITS_TO_BYTES(pPhase1OpData->privateValueX.dataLenInBytes,
+                     krp->krp_param[ICP_DH_KRP_PARAM_PRIVATE_VALUE_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(pPhase1OpData->privateValueX.pData,
+                           pPhase1OpData->privateValueX.dataLenInBytes);
+
+       /* Output parameters */
+       pLocalOctetStringPV->pData =
+           krp->krp_param[ICP_DH_KRP_PARAM_RESULT_INDEX].crp_p;
+
+       BITS_TO_BYTES(pLocalOctetStringPV->dataLenInBytes,
+                     krp->krp_param[ICP_DH_KRP_PARAM_RESULT_INDEX].crp_nbits);
+
+       lacStatus = cpaCyDhKeyGenPhase1(CPA_INSTANCE_HANDLE_SINGLE,
+                                       icp_ocfDrvDhP1CallBack,
+                                       callbackTag, pPhase1OpData,
+                                       pLocalOctetStringPV);
+
+       if (CPA_STATUS_SUCCESS != lacStatus) {
+               EPRINTK("%s(): DH Phase 1 Key Gen failed (%d).\n",
+                       __FUNCTION__, lacStatus);
+               icp_ocfDrvFreeFlatBuffer(pLocalOctetStringPV);
+               ICP_CACHE_FREE(drvDH_zone, pPhase1OpData);
+       }
+
+       return lacStatus;
+}
+
+/* Name        : icp_ocfDrvModExp
+ *
+ * Description : This function will map ordinary Modular Exponentiation calls
+ * from OCF to the LAC API.
+ *
+ */
+static int icp_ocfDrvModExp(struct cryptkop *krp)
+{
+       CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+       void *callbackTag = NULL;
+       CpaCyLnModExpOpData *pModExpOpData = NULL;
+       CpaFlatBuffer *pResult = NULL;
+
+       if ((krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].crp_nbits %
+            NUM_BITS_IN_BYTE) != 0) {
+               DPRINTK("%s(): Warning - modulus buffer size (%d) is not a "
+                       "multiple of 8 bits\n", __FUNCTION__,
+                       krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].
+                       crp_nbits);
+       }
+
+       /* Result storage space should be the same size as the prime as this
+          value can take up the same amount of storage space */
+       if (krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].crp_nbits >
+           krp->krp_param[ICP_MOD_EXP_KRP_PARAM_RESULT_INDEX].crp_nbits) {
+               APRINTK("%s(): Return Buffer size must be the same or"
+                       " greater than the Modulus buffer\n", __FUNCTION__);
+               krp->krp_status = EINVAL;
+               return EINVAL;
+       }
+
+       callbackTag = krp;
+
+       pModExpOpData = icp_kmem_cache_zalloc(drvLnModExp_zone, ICP_M_NOWAIT);
+       if (NULL == pModExpOpData) {
+               APRINTK("%s():Failed to get memory for key gen data\n",
+                       __FUNCTION__);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       pResult = icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
+       if (NULL == pResult) {
+               APRINTK("%s():Failed to get memory for ModExp result\n",
+                       __FUNCTION__);
+               ICP_CACHE_FREE(drvLnModExp_zone, pModExpOpData);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       /* Link parameters */
+       pModExpOpData->modulus.pData =
+           krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].crp_p;
+       BITS_TO_BYTES(pModExpOpData->modulus.dataLenInBytes,
+                     krp->krp_param[ICP_MOD_EXP_KRP_PARAM_MODULUS_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(pModExpOpData->modulus.pData,
+                           pModExpOpData->modulus.dataLenInBytes);
+
+       DPRINTK("%s : base (%d)\n", __FUNCTION__, krp->
+               krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].crp_nbits);
+       pModExpOpData->base.pData =
+           krp->krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].crp_p;
+       BITS_TO_BYTES(pModExpOpData->base.dataLenInBytes,
+                     krp->krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].
+                     crp_nbits);
+       icp_ocfDrvSwapBytes(pModExpOpData->base.pData,
+                           pModExpOpData->base.dataLenInBytes);
+
+       pModExpOpData->exponent.pData =
+           krp->krp_param[ICP_MOD_EXP_KRP_PARAM_EXPONENT_INDEX].crp_p;
+       BITS_TO_BYTES(pModExpOpData->exponent.dataLenInBytes,
+                     krp->krp_param[ICP_MOD_EXP_KRP_PARAM_EXPONENT_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(pModExpOpData->exponent.pData,
+                           pModExpOpData->exponent.dataLenInBytes);
+       /* Output parameters */
+       pResult->pData =
+           krp->krp_param[ICP_MOD_EXP_KRP_PARAM_RESULT_INDEX].crp_p,
+           BITS_TO_BYTES(pResult->dataLenInBytes,
+                         krp->krp_param[ICP_MOD_EXP_KRP_PARAM_RESULT_INDEX].
+                         crp_nbits);
+
+       lacStatus = cpaCyLnModExp(CPA_INSTANCE_HANDLE_SINGLE,
+                                 icp_ocfDrvModExpCallBack,
+                                 callbackTag, pModExpOpData, pResult);
+
+       if (CPA_STATUS_SUCCESS != lacStatus) {
+               EPRINTK("%s(): Mod Exp Operation failed (%d).\n",
+                       __FUNCTION__, lacStatus);
+               krp->krp_status = ECANCELED;
+               icp_ocfDrvFreeFlatBuffer(pResult);
+               ICP_CACHE_FREE(drvLnModExp_zone, pModExpOpData);
+       }
+
+       return lacStatus;
+}
+
+/* Name        : icp_ocfDrvModExpCRT
+ *
+ * Description : This function will map ordinary Modular Exponentiation Chinese
+ * Remainder Theorem implementaion calls from OCF to the LAC API.
+ *
+ * Note : Mod Exp CRT for this driver is accelerated through LAC RSA type 2
+ * decrypt operation. Therefore P and Q input values must always be prime
+ * numbers. Although basic primality checks are done in LAC, it is up to the
+ * user to do any correct prime number checking before passing the inputs.
+ */
+static int icp_ocfDrvModExpCRT(struct cryptkop *krp)
+{
+       CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+       CpaCyRsaDecryptOpData *rsaDecryptOpData = NULL;
+       void *callbackTag = NULL;
+       CpaFlatBuffer *pOutputData = NULL;
+
+       /*Parameter input checks are all done by LAC, no need to repeat
+          them here. */
+       callbackTag = krp;
+
+       rsaDecryptOpData =
+           icp_kmem_cache_zalloc(drvRSADecrypt_zone, ICP_M_NOWAIT);
+       if (NULL == rsaDecryptOpData) {
+               APRINTK("%s():Failed to get memory"
+                       " for MOD EXP CRT Op data struct\n", __FUNCTION__);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       rsaDecryptOpData->pRecipientPrivateKey
+           = icp_kmem_cache_zalloc(drvRSAPrivateKey_zone, ICP_M_NOWAIT);
+       if (NULL == rsaDecryptOpData->pRecipientPrivateKey) {
+               APRINTK("%s():Failed to get memory for MOD EXP CRT"
+                       " private key values struct\n", __FUNCTION__);
+               ICP_CACHE_FREE(drvRSADecrypt_zone, rsaDecryptOpData);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       rsaDecryptOpData->pRecipientPrivateKey->
+           version = CPA_CY_RSA_VERSION_TWO_PRIME;
+       rsaDecryptOpData->pRecipientPrivateKey->
+           privateKeyRepType = CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2;
+
+       pOutputData = icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
+       if (NULL == pOutputData) {
+               APRINTK("%s():Failed to get memory"
+                       " for MOD EXP CRT output data\n", __FUNCTION__);
+               ICP_CACHE_FREE(drvRSAPrivateKey_zone,
+                              rsaDecryptOpData->pRecipientPrivateKey);
+               ICP_CACHE_FREE(drvRSADecrypt_zone, rsaDecryptOpData);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       rsaDecryptOpData->pRecipientPrivateKey->
+           version = CPA_CY_RSA_VERSION_TWO_PRIME;
+       rsaDecryptOpData->pRecipientPrivateKey->
+           privateKeyRepType = CPA_CY_RSA_PRIVATE_KEY_REP_TYPE_2;
+
+       /* Link parameters */
+       rsaDecryptOpData->inputData.pData =
+           krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_I_INDEX].crp_p;
+       BITS_TO_BYTES(rsaDecryptOpData->inputData.dataLenInBytes,
+                     krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_I_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(rsaDecryptOpData->inputData.pData,
+                           rsaDecryptOpData->inputData.dataLenInBytes);
+
+       rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime1P.pData =
+           krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_P_INDEX].crp_p;
+       BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.
+                     prime1P.dataLenInBytes,
+                     krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_P_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.prime1P.pData,
+                           rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.prime1P.dataLenInBytes);
+
+       rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.prime2Q.pData =
+           krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_Q_INDEX].crp_p;
+       BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.
+                     prime2Q.dataLenInBytes,
+                     krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_PRIME_Q_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.prime2Q.pData,
+                           rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.prime2Q.dataLenInBytes);
+
+       rsaDecryptOpData->pRecipientPrivateKey->
+           privateKeyRep2.exponent1Dp.pData =
+           krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DP_INDEX].crp_p;
+       BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->privateKeyRep2.
+                     exponent1Dp.dataLenInBytes,
+                     krp->
+                     krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DP_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.exponent1Dp.pData,
+                           rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.exponent1Dp.dataLenInBytes);
+
+       rsaDecryptOpData->pRecipientPrivateKey->
+           privateKeyRep2.exponent2Dq.pData =
+           krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DQ_INDEX].crp_p;
+       BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->
+                     privateKeyRep2.exponent2Dq.dataLenInBytes,
+                     krp->
+                     krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_EXPONENT_DQ_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.exponent2Dq.pData,
+                           rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.exponent2Dq.dataLenInBytes);
+
+       rsaDecryptOpData->pRecipientPrivateKey->
+           privateKeyRep2.coefficientQInv.pData =
+           krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_COEFF_QINV_INDEX].crp_p;
+       BITS_TO_BYTES(rsaDecryptOpData->pRecipientPrivateKey->
+                     privateKeyRep2.coefficientQInv.dataLenInBytes,
+                     krp->
+                     krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_COEFF_QINV_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.coefficientQInv.pData,
+                           rsaDecryptOpData->pRecipientPrivateKey->
+                           privateKeyRep2.coefficientQInv.dataLenInBytes);
+
+       /* Output Parameter */
+       pOutputData->pData =
+           krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_RESULT_INDEX].crp_p;
+       BITS_TO_BYTES(pOutputData->dataLenInBytes,
+                     krp->krp_param[ICP_MOD_EXP_CRT_KRP_PARAM_RESULT_INDEX].
+                     crp_nbits);
+
+       lacStatus = cpaCyRsaDecrypt(CPA_INSTANCE_HANDLE_SINGLE,
+                                   icp_ocfDrvModExpCRTCallBack,
+                                   callbackTag, rsaDecryptOpData, pOutputData);
+
+       if (CPA_STATUS_SUCCESS != lacStatus) {
+               EPRINTK("%s(): Mod Exp CRT Operation failed (%d).\n",
+                       __FUNCTION__, lacStatus);
+               krp->krp_status = ECANCELED;
+               icp_ocfDrvFreeFlatBuffer(pOutputData);
+               ICP_CACHE_FREE(drvRSAPrivateKey_zone,
+                              rsaDecryptOpData->pRecipientPrivateKey);
+               ICP_CACHE_FREE(drvRSADecrypt_zone, rsaDecryptOpData);
+       }
+
+       return lacStatus;
+}
+
+/* Name        : icp_ocfDrvCheckALessThanB
+ *
+ * Description : This function will check whether the first argument is less
+ * than the second. It is used to check whether the DSA RS sign Random K
+ * value is less than the Prime Q value (as defined in the specification)
+ *
+ */
+static int
+icp_ocfDrvCheckALessThanB(CpaFlatBuffer * pK, CpaFlatBuffer * pQ, int *doCheck)
+{
+
+       uint8_t *MSB_K = pK->pData;
+       uint8_t *MSB_Q = pQ->pData;
+       uint32_t buffer_lengths_in_bytes = pQ->dataLenInBytes;
+
+       if (DONT_RUN_LESS_THAN_CHECK == *doCheck) {
+               return FAIL_A_IS_GREATER_THAN_B;
+       }
+
+/*Check MSBs
+if A == B, check next MSB
+if A > B, return A_IS_GREATER_THAN_B
+if A < B, return A_IS_LESS_THAN_B (success)
+*/
+       while (*MSB_K == *MSB_Q) {
+               MSB_K++;
+               MSB_Q++;
+
+               buffer_lengths_in_bytes--;
+               if (0 == buffer_lengths_in_bytes) {
+                       DPRINTK("%s() Buffers have equal value!!\n",
+                               __FUNCTION__);
+                       return FAIL_A_IS_EQUAL_TO_B;
+               }
+
+       }
+
+       if (*MSB_K < *MSB_Q) {
+               return SUCCESS_A_IS_LESS_THAN_B;
+       } else {
+               return FAIL_A_IS_GREATER_THAN_B;
+       }
+
+}
+
+/* Name        : icp_ocfDrvDsaSign
+ *
+ * Description : This function will map DSA RS Sign from OCF to the LAC API.
+ *
+ * NOTE: From looking at OCF patch to OpenSSL and even the number of input
+ * parameters, OCF expects us to generate the random seed value. This value
+ * is generated and passed to LAC, however the number is discared in the
+ * callback and not returned to the user.
+ */
+static int icp_ocfDrvDsaSign(struct cryptkop *krp)
+{
+       CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+       CpaCyDsaRSSignOpData *dsaRsSignOpData = NULL;
+       void *callbackTag = NULL;
+       CpaCyRandGenOpData randGenOpData;
+       int primeQSizeInBytes = 0;
+       int doCheck = 0;
+       CpaFlatBuffer randData;
+       CpaBoolean protocolStatus = CPA_FALSE;
+       CpaFlatBuffer *pR = NULL;
+       CpaFlatBuffer *pS = NULL;
+
+       callbackTag = krp;
+
+       BITS_TO_BYTES(primeQSizeInBytes,
+                     krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_Q_INDEX].
+                     crp_nbits);
+
+       if (DSA_RS_SIGN_PRIMEQ_SIZE_IN_BYTES != primeQSizeInBytes) {
+               APRINTK("%s(): DSA PRIME Q size not equal to the "
+                       "FIPS defined 20bytes, = %d\n",
+                       __FUNCTION__, primeQSizeInBytes);
+               krp->krp_status = EDOM;
+               return EDOM;
+       }
+
+       dsaRsSignOpData =
+           icp_kmem_cache_zalloc(drvDSARSSign_zone, ICP_M_NOWAIT);
+       if (NULL == dsaRsSignOpData) {
+               APRINTK("%s():Failed to get memory"
+                       " for DSA RS Sign Op data struct\n", __FUNCTION__);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       dsaRsSignOpData->K.pData =
+           icp_kmem_cache_alloc(drvDSARSSignKValue_zone, ICP_M_NOWAIT);
+
+       if (NULL == dsaRsSignOpData->K.pData) {
+               APRINTK("%s():Failed to get memory"
+                       " for DSA RS Sign Op Random value\n", __FUNCTION__);
+               ICP_CACHE_FREE(drvDSARSSign_zone, dsaRsSignOpData);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       pR = icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
+       if (NULL == pR) {
+               APRINTK("%s():Failed to get memory"
+                       " for DSA signature R\n", __FUNCTION__);
+               ICP_CACHE_FREE(drvDSARSSignKValue_zone,
+                              dsaRsSignOpData->K.pData);
+               ICP_CACHE_FREE(drvDSARSSign_zone, dsaRsSignOpData);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       pS = icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
+       if (NULL == pS) {
+               APRINTK("%s():Failed to get memory"
+                       " for DSA signature S\n", __FUNCTION__);
+               icp_ocfDrvFreeFlatBuffer(pR);
+               ICP_CACHE_FREE(drvDSARSSignKValue_zone,
+                              dsaRsSignOpData->K.pData);
+               ICP_CACHE_FREE(drvDSARSSign_zone, dsaRsSignOpData);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       /*link prime number parameter for ease of processing */
+       dsaRsSignOpData->P.pData =
+           krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_P_INDEX].crp_p;
+       BITS_TO_BYTES(dsaRsSignOpData->P.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_P_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(dsaRsSignOpData->P.pData,
+                           dsaRsSignOpData->P.dataLenInBytes);
+
+       dsaRsSignOpData->Q.pData =
+           krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_Q_INDEX].crp_p;
+       BITS_TO_BYTES(dsaRsSignOpData->Q.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_PRIME_Q_INDEX].
+                     crp_nbits);
+
+       icp_ocfDrvSwapBytes(dsaRsSignOpData->Q.pData,
+                           dsaRsSignOpData->Q.dataLenInBytes);
+
+       /*generate random number with equal buffer size to Prime value Q,
+          but value less than Q */
+       dsaRsSignOpData->K.dataLenInBytes = dsaRsSignOpData->Q.dataLenInBytes;
+
+       randGenOpData.generateBits = CPA_TRUE;
+       randGenOpData.lenInBytes = dsaRsSignOpData->K.dataLenInBytes;
+
+       icp_ocfDrvPtrAndLenToFlatBuffer(dsaRsSignOpData->K.pData,
+                                       dsaRsSignOpData->K.dataLenInBytes,
+                                       &randData);
+
+       doCheck = 0;
+       while (icp_ocfDrvCheckALessThanB(&(dsaRsSignOpData->K),
+                                        &(dsaRsSignOpData->Q), &doCheck)) {
+
+               if (CPA_STATUS_SUCCESS
+                   != cpaCyRandGen(CPA_INSTANCE_HANDLE_SINGLE,
+                                   NULL, NULL, &randGenOpData, &randData)) {
+                       APRINTK("%s(): ERROR - Failed to generate DSA RS Sign K"
+                               "value\n", __FUNCTION__);
+                       icp_ocfDrvFreeFlatBuffer(pS);
+                       icp_ocfDrvFreeFlatBuffer(pR);
+                       ICP_CACHE_FREE(drvDSARSSignKValue_zone,
+                                      dsaRsSignOpData->K.pData);
+                       ICP_CACHE_FREE(drvDSARSSign_zone, dsaRsSignOpData);
+                       krp->krp_status = EAGAIN;
+                       return EAGAIN;
+               }
+
+               doCheck++;
+               if (DSA_SIGN_RAND_GEN_VAL_CHECK_MAX_ITERATIONS == doCheck) {
+                       APRINTK("%s(): ERROR - Failed to find DSA RS Sign K "
+                               "value less than Q value\n", __FUNCTION__);
+                       icp_ocfDrvFreeFlatBuffer(pS);
+                       icp_ocfDrvFreeFlatBuffer(pR);
+                       ICP_CACHE_FREE(drvDSARSSignKValue_zone,
+                                      dsaRsSignOpData->K.pData);
+                       ICP_CACHE_FREE(drvDSARSSign_zone, dsaRsSignOpData);
+                       krp->krp_status = EAGAIN;
+                       return EAGAIN;
+               }
+
+       }
+       /*Rand Data - no need to swap bytes for pK */
+
+       /* Link parameters */
+       dsaRsSignOpData->G.pData =
+           krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_G_INDEX].crp_p;
+       BITS_TO_BYTES(dsaRsSignOpData->G.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_G_INDEX].crp_nbits);
+
+       icp_ocfDrvSwapBytes(dsaRsSignOpData->G.pData,
+                           dsaRsSignOpData->G.dataLenInBytes);
+
+       dsaRsSignOpData->X.pData =
+           krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_X_INDEX].crp_p;
+       BITS_TO_BYTES(dsaRsSignOpData->X.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_X_INDEX].crp_nbits);
+       icp_ocfDrvSwapBytes(dsaRsSignOpData->X.pData,
+                           dsaRsSignOpData->X.dataLenInBytes);
+
+       /*OpenSSL dgst parameter is left in big endian byte order, 
+          therefore no byte swap is required */
+       dsaRsSignOpData->M.pData =
+           krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_DGST_INDEX].crp_p;
+       BITS_TO_BYTES(dsaRsSignOpData->M.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_DGST_INDEX].
+                     crp_nbits);
+
+       /* Output Parameters */
+       pS->pData = krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_S_RESULT_INDEX].crp_p;
+       BITS_TO_BYTES(pS->dataLenInBytes,
+                     krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_S_RESULT_INDEX].
+                     crp_nbits);
+
+       pR->pData = krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_R_RESULT_INDEX].crp_p;
+       BITS_TO_BYTES(pR->dataLenInBytes,
+                     krp->krp_param[ICP_DSA_SIGN_KRP_PARAM_R_RESULT_INDEX].
+                     crp_nbits);
+
+       lacStatus = cpaCyDsaSignRS(CPA_INSTANCE_HANDLE_SINGLE,
+                                  icp_ocfDrvDsaRSSignCallBack,
+                                  callbackTag, dsaRsSignOpData,
+                                  &protocolStatus, pR, pS);
+
+       if (CPA_STATUS_SUCCESS != lacStatus) {
+               EPRINTK("%s(): DSA RS Sign Operation failed (%d).\n",
+                       __FUNCTION__, lacStatus);
+               krp->krp_status = ECANCELED;
+               icp_ocfDrvFreeFlatBuffer(pS);
+               icp_ocfDrvFreeFlatBuffer(pR);
+               ICP_CACHE_FREE(drvDSARSSignKValue_zone,
+                              dsaRsSignOpData->K.pData);
+               ICP_CACHE_FREE(drvDSARSSign_zone, dsaRsSignOpData);
+       }
+
+       return lacStatus;
+}
+
+/* Name        : icp_ocfDrvDsaVerify
+ *
+ * Description : This function will map DSA RS Verify from OCF to the LAC API.
+ *
+ */
+static int icp_ocfDrvDsaVerify(struct cryptkop *krp)
+{
+       CpaStatus lacStatus = CPA_STATUS_SUCCESS;
+       CpaCyDsaVerifyOpData *dsaVerifyOpData = NULL;
+       void *callbackTag = NULL;
+       CpaBoolean verifyStatus = CPA_FALSE;
+
+       callbackTag = krp;
+
+       dsaVerifyOpData =
+           icp_kmem_cache_zalloc(drvDSAVerify_zone, ICP_M_NOWAIT);
+       if (NULL == dsaVerifyOpData) {
+               APRINTK("%s():Failed to get memory"
+                       " for DSA Verify Op data struct\n", __FUNCTION__);
+               krp->krp_status = ENOMEM;
+               return ENOMEM;
+       }
+
+       /* Link parameters */
+       dsaVerifyOpData->P.pData =
+           krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PRIME_P_INDEX].crp_p;
+       BITS_TO_BYTES(dsaVerifyOpData->P.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PRIME_P_INDEX].
+                     crp_nbits);
+       icp_ocfDrvSwapBytes(dsaVerifyOpData->P.pData,
+                           dsaVerifyOpData->P.dataLenInBytes);
+
+       dsaVerifyOpData->Q.pData =
+           krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PRIME_Q_INDEX].crp_p;
+       BITS_TO_BYTES(dsaVerifyOpData->Q.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PRIME_Q_INDEX].
+                     crp_nbits);
+       icp_ocfDrvSwapBytes(dsaVerifyOpData->Q.pData,
+                           dsaVerifyOpData->Q.dataLenInBytes);
+
+       dsaVerifyOpData->G.pData =
+           krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_G_INDEX].crp_p;
+       BITS_TO_BYTES(dsaVerifyOpData->G.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_G_INDEX].
+                     crp_nbits);
+       icp_ocfDrvSwapBytes(dsaVerifyOpData->G.pData,
+                           dsaVerifyOpData->G.dataLenInBytes);
+
+       dsaVerifyOpData->Y.pData =
+           krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PUBKEY_INDEX].crp_p;
+       BITS_TO_BYTES(dsaVerifyOpData->Y.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_PUBKEY_INDEX].
+                     crp_nbits);
+       icp_ocfDrvSwapBytes(dsaVerifyOpData->Y.pData,
+                           dsaVerifyOpData->Y.dataLenInBytes);
+
+       /*OpenSSL dgst parameter is left in big endian byte order, 
+          therefore no byte swap is required */
+       dsaVerifyOpData->M.pData =
+           krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_DGST_INDEX].crp_p;
+       BITS_TO_BYTES(dsaVerifyOpData->M.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_DGST_INDEX].
+                     crp_nbits);
+
+       dsaVerifyOpData->R.pData =
+           krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_SIG_R_INDEX].crp_p;
+       BITS_TO_BYTES(dsaVerifyOpData->R.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_SIG_R_INDEX].
+                     crp_nbits);
+       icp_ocfDrvSwapBytes(dsaVerifyOpData->R.pData,
+                           dsaVerifyOpData->R.dataLenInBytes);
+
+       dsaVerifyOpData->S.pData =
+           krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_SIG_S_INDEX].crp_p;
+       BITS_TO_BYTES(dsaVerifyOpData->S.dataLenInBytes,
+                     krp->krp_param[ICP_DSA_VERIFY_KRP_PARAM_SIG_S_INDEX].
+                     crp_nbits);
+       icp_ocfDrvSwapBytes(dsaVerifyOpData->S.pData,
+                           dsaVerifyOpData->S.dataLenInBytes);
+
+       lacStatus = cpaCyDsaVerify(CPA_INSTANCE_HANDLE_SINGLE,
+                                  icp_ocfDrvDsaVerifyCallBack,
+                                  callbackTag, dsaVerifyOpData, &verifyStatus);
+
+       if (CPA_STATUS_SUCCESS != lacStatus) {
+               EPRINTK("%s(): DSA Verify Operation failed (%d).\n",
+                       __FUNCTION__, lacStatus);
+               ICP_CACHE_FREE(drvDSAVerify_zone, dsaVerifyOpData);
+               krp->krp_status = ECANCELED;
+       }
+
+       return lacStatus;
+}
+
+/* Name        : icp_ocfDrvDhP1Callback
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the DH operation.
+ */
+static void
+icp_ocfDrvDhP1CallBack(void *callbackTag,
+                      CpaStatus status,
+                      void *pOpData, CpaFlatBuffer * pLocalOctetStringPV)
+{
+       struct cryptkop *krp = NULL;
+       CpaCyDhPhase1KeyGenOpData *pPhase1OpData = NULL;
+
+       if (NULL == callbackTag) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "callbackTag data is NULL\n", __FUNCTION__);
+               return;
+       }
+       krp = (struct cryptkop *)callbackTag;
+
+       if (NULL == pOpData) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "Operation Data is NULL\n", __FUNCTION__);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+       pPhase1OpData = (CpaCyDhPhase1KeyGenOpData *) pOpData;
+
+       if (NULL == pLocalOctetStringPV) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "pLocalOctetStringPV Data is NULL\n", __FUNCTION__);
+               memset(pPhase1OpData, 0, sizeof(CpaCyDhPhase1KeyGenOpData));
+               ICP_CACHE_FREE(drvDH_zone, pPhase1OpData);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+
+       if (CPA_STATUS_SUCCESS == status) {
+               krp->krp_status = CRYPTO_OP_SUCCESS;
+       } else {
+               APRINTK("%s(): Diffie Hellman Phase1 Key Gen failed - "
+                       "Operation Status = %d\n", __FUNCTION__, status);
+               krp->krp_status = ECANCELED;
+       }
+
+       icp_ocfDrvSwapBytes(pLocalOctetStringPV->pData,
+                           pLocalOctetStringPV->dataLenInBytes);
+
+       icp_ocfDrvFreeFlatBuffer(pLocalOctetStringPV);
+       memset(pPhase1OpData, 0, sizeof(CpaCyDhPhase1KeyGenOpData));
+       ICP_CACHE_FREE(drvDH_zone, pPhase1OpData);
+
+       crypto_kdone(krp);
+
+       return;
+}
+
+/* Name        : icp_ocfDrvModExpCallBack
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the Mod Exp operation.
+ */
+static void
+icp_ocfDrvModExpCallBack(void *callbackTag,
+                        CpaStatus status,
+                        void *pOpdata, CpaFlatBuffer * pResult)
+{
+       struct cryptkop *krp = NULL;
+       CpaCyLnModExpOpData *pLnModExpOpData = NULL;
+
+       if (NULL == callbackTag) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "callbackTag data is NULL\n", __FUNCTION__);
+               return;
+       }
+       krp = (struct cryptkop *)callbackTag;
+
+       if (NULL == pOpdata) {
+               DPRINTK("%s(): Invalid Mod Exp input parameters - "
+                       "Operation Data is NULL\n", __FUNCTION__);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+       pLnModExpOpData = (CpaCyLnModExpOpData *) pOpdata;
+
+       if (NULL == pResult) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "pResult data is NULL\n", __FUNCTION__);
+               krp->krp_status = ECANCELED;
+               memset(pLnModExpOpData, 0, sizeof(CpaCyLnModExpOpData));
+               ICP_CACHE_FREE(drvLnModExp_zone, pLnModExpOpData);
+               crypto_kdone(krp);
+               return;
+       }
+
+       if (CPA_STATUS_SUCCESS == status) {
+               krp->krp_status = CRYPTO_OP_SUCCESS;
+       } else {
+               APRINTK("%s(): LAC Mod Exp Operation failed - "
+                       "Operation Status = %d\n", __FUNCTION__, status);
+               krp->krp_status = ECANCELED;
+       }
+
+       icp_ocfDrvSwapBytes(pResult->pData, pResult->dataLenInBytes);
+
+       /*switch base size value back to original */
+       if (pLnModExpOpData->base.pData ==
+           (uint8_t *) & (krp->
+                          krp_param[ICP_MOD_EXP_KRP_PARAM_BASE_INDEX].
+                          crp_nbits)) {
+               *((uint32_t *) pLnModExpOpData->base.pData) =
+                   ntohl(*((uint32_t *) pLnModExpOpData->base.pData));
+       }
+       icp_ocfDrvFreeFlatBuffer(pResult);
+       memset(pLnModExpOpData, 0, sizeof(CpaCyLnModExpOpData));
+       ICP_CACHE_FREE(drvLnModExp_zone, pLnModExpOpData);
+
+       crypto_kdone(krp);
+
+       return;
+
+}
+
+/* Name        : icp_ocfDrvModExpCRTCallBack
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the Mod Exp CRT operation.
+ */
+static void
+icp_ocfDrvModExpCRTCallBack(void *callbackTag,
+                           CpaStatus status,
+                           void *pOpData, CpaFlatBuffer * pOutputData)
+{
+       struct cryptkop *krp = NULL;
+       CpaCyRsaDecryptOpData *pDecryptData = NULL;
+
+       if (NULL == callbackTag) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "callbackTag data is NULL\n", __FUNCTION__);
+               return;
+       }
+
+       krp = (struct cryptkop *)callbackTag;
+
+       if (NULL == pOpData) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "Operation Data is NULL\n", __FUNCTION__);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+       pDecryptData = (CpaCyRsaDecryptOpData *) pOpData;
+
+       if (NULL == pOutputData) {
+               DPRINTK("%s(): Invalid input parameter - "
+                       "pOutputData is NULL\n", __FUNCTION__);
+               memset(pDecryptData->pRecipientPrivateKey, 0,
+                      sizeof(CpaCyRsaPrivateKey));
+               ICP_CACHE_FREE(drvRSAPrivateKey_zone,
+                              pDecryptData->pRecipientPrivateKey);
+               memset(pDecryptData, 0, sizeof(CpaCyRsaDecryptOpData));
+               ICP_CACHE_FREE(drvRSADecrypt_zone, pDecryptData);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+
+       if (CPA_STATUS_SUCCESS == status) {
+               krp->krp_status = CRYPTO_OP_SUCCESS;
+       } else {
+               APRINTK("%s(): LAC Mod Exp CRT operation failed - "
+                       "Operation Status = %d\n", __FUNCTION__, status);
+               krp->krp_status = ECANCELED;
+       }
+
+       icp_ocfDrvSwapBytes(pOutputData->pData, pOutputData->dataLenInBytes);
+
+       icp_ocfDrvFreeFlatBuffer(pOutputData);
+       memset(pDecryptData->pRecipientPrivateKey, 0,
+              sizeof(CpaCyRsaPrivateKey));
+       ICP_CACHE_FREE(drvRSAPrivateKey_zone,
+                      pDecryptData->pRecipientPrivateKey);
+       memset(pDecryptData, 0, sizeof(CpaCyRsaDecryptOpData));
+       ICP_CACHE_FREE(drvRSADecrypt_zone, pDecryptData);
+
+       crypto_kdone(krp);
+
+       return;
+}
+
+/* Name        : icp_ocfDrvDsaRSSignCallBack
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the DSA RS sign operation.
+ */
+static void
+icp_ocfDrvDsaRSSignCallBack(void *callbackTag,
+                           CpaStatus status,
+                           void *pOpData,
+                           CpaBoolean protocolStatus,
+                           CpaFlatBuffer * pR, CpaFlatBuffer * pS)
+{
+       struct cryptkop *krp = NULL;
+       CpaCyDsaRSSignOpData *pSignData = NULL;
+
+       if (NULL == callbackTag) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "callbackTag data is NULL\n", __FUNCTION__);
+               return;
+       }
+
+       krp = (struct cryptkop *)callbackTag;
+
+       if (NULL == pOpData) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "Operation Data is NULL\n", __FUNCTION__);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+       pSignData = (CpaCyDsaRSSignOpData *) pOpData;
+
+       if (NULL == pR) {
+               DPRINTK("%s(): Invalid input parameter - "
+                       "pR sign is NULL\n", __FUNCTION__);
+               icp_ocfDrvFreeFlatBuffer(pS);
+               ICP_CACHE_FREE(drvDSARSSign_zone, pSignData);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+
+       if (NULL == pS) {
+               DPRINTK("%s(): Invalid input parameter - "
+                       "pS sign is NULL\n", __FUNCTION__);
+               icp_ocfDrvFreeFlatBuffer(pR);
+               ICP_CACHE_FREE(drvDSARSSign_zone, pSignData);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+
+       if (CPA_STATUS_SUCCESS != status) {
+               APRINTK("%s(): LAC DSA RS Sign operation failed - "
+                       "Operation Status = %d\n", __FUNCTION__, status);
+               krp->krp_status = ECANCELED;
+       } else {
+               krp->krp_status = CRYPTO_OP_SUCCESS;
+
+               if (CPA_TRUE != protocolStatus) {
+                       DPRINTK("%s(): LAC DSA RS Sign operation failed due "
+                               "to protocol error\n", __FUNCTION__);
+                       krp->krp_status = EIO;
+               }
+       }
+
+       /* Swap bytes only when the callback status is successful and
+          protocolStatus is set to true */
+       if (CPA_STATUS_SUCCESS == status && CPA_TRUE == protocolStatus) {
+               icp_ocfDrvSwapBytes(pR->pData, pR->dataLenInBytes);
+               icp_ocfDrvSwapBytes(pS->pData, pS->dataLenInBytes);
+       }
+
+       icp_ocfDrvFreeFlatBuffer(pR);
+       icp_ocfDrvFreeFlatBuffer(pS);
+       memset(pSignData->K.pData, 0, pSignData->K.dataLenInBytes);
+       ICP_CACHE_FREE(drvDSARSSignKValue_zone, pSignData->K.pData);
+       memset(pSignData, 0, sizeof(CpaCyDsaRSSignOpData));
+       ICP_CACHE_FREE(drvDSARSSign_zone, pSignData);
+       crypto_kdone(krp);
+
+       return;
+}
+
+/* Name        : icp_ocfDrvDsaVerifyCallback
+ *
+ * Description : When this function returns it signifies that the LAC
+ * component has completed the DSA Verify operation.
+ */
+static void
+icp_ocfDrvDsaVerifyCallBack(void *callbackTag,
+                           CpaStatus status,
+                           void *pOpData, CpaBoolean verifyStatus)
+{
+
+       struct cryptkop *krp = NULL;
+       CpaCyDsaVerifyOpData *pVerData = NULL;
+
+       if (NULL == callbackTag) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "callbackTag data is NULL\n", __FUNCTION__);
+               return;
+       }
+
+       krp = (struct cryptkop *)callbackTag;
+
+       if (NULL == pOpData) {
+               DPRINTK("%s(): Invalid input parameters - "
+                       "Operation Data is NULL\n", __FUNCTION__);
+               krp->krp_status = ECANCELED;
+               crypto_kdone(krp);
+               return;
+       }
+       pVerData = (CpaCyDsaVerifyOpData *) pOpData;
+
+       if (CPA_STATUS_SUCCESS != status) {
+               APRINTK("%s(): LAC DSA Verify operation failed - "
+                       "Operation Status = %d\n", __FUNCTION__, status);
+               krp->krp_status = ECANCELED;
+       } else {
+               krp->krp_status = CRYPTO_OP_SUCCESS;
+
+               if (CPA_TRUE != verifyStatus) {
+                       DPRINTK("%s(): DSA signature invalid\n", __FUNCTION__);
+                       krp->krp_status = EIO;
+               }
+       }
+
+       /* Swap bytes only when the callback status is successful and
+          verifyStatus is set to true */
+       /*Just swapping back the key values for now. Possibly all
+          swapped buffers need to be reverted */
+       if (CPA_STATUS_SUCCESS == status && CPA_TRUE == verifyStatus) {
+               icp_ocfDrvSwapBytes(pVerData->R.pData,
+                                   pVerData->R.dataLenInBytes);
+               icp_ocfDrvSwapBytes(pVerData->S.pData,
+                                   pVerData->S.dataLenInBytes);
+       }
+
+       memset(pVerData, 0, sizeof(CpaCyDsaVerifyOpData));
+       ICP_CACHE_FREE(drvDSAVerify_zone, pVerData);
+       crypto_kdone(krp);
+
+       return;
+}