X-Git-Url: https://git.archive.openwrt.org/?p=15.05%2Fopenwrt.git;a=blobdiff_plain;f=target%2Flinux%2Fgeneric%2Ffiles%2Fcrypto%2Focf%2Fep80579%2Ficp_asym.c;fp=target%2Flinux%2Fgeneric%2Ffiles%2Fcrypto%2Focf%2Fep80579%2Ficp_asym.c;h=d2641c545509461e1bfbd906ae7372066d94d9c6;hp=0000000000000000000000000000000000000000;hb=a082943b09f4f707990ad0ac6326df8480507f02;hpb=67fbcc7bd42cc07b1f3c6b5c9f2db37647178f25 diff --git a/target/linux/generic/files/crypto/ocf/ep80579/icp_asym.c b/target/linux/generic/files/crypto/ocf/ep80579/icp_asym.c new file mode 100644 index 0000000000..d2641c5455 --- /dev/null +++ b/target/linux/generic/files/crypto/ocf/ep80579/icp_asym.c @@ -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; +}