aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/files/crypto/ocf/kirkwood/cesa/mvCesa.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/files/crypto/ocf/kirkwood/cesa/mvCesa.c')
-rw-r--r--target/linux/generic/files/crypto/ocf/kirkwood/cesa/mvCesa.c3126
1 files changed, 3126 insertions, 0 deletions
diff --git a/target/linux/generic/files/crypto/ocf/kirkwood/cesa/mvCesa.c b/target/linux/generic/files/crypto/ocf/kirkwood/cesa/mvCesa.c
new file mode 100644
index 000000000..17ab086f0
--- /dev/null
+++ b/target/linux/generic/files/crypto/ocf/kirkwood/cesa/mvCesa.c
@@ -0,0 +1,3126 @@
+/*******************************************************************************
+Copyright (C) Marvell International Ltd. and its affiliates
+
+This software file (the "File") is owned and distributed by Marvell
+International Ltd. and/or its affiliates ("Marvell") under the following
+alternative licensing terms. Once you have made an election to distribute the
+File under one of the following license alternatives, please (i) delete this
+introductory statement regarding license alternatives, (ii) delete the two
+license alternatives that you have not elected to use and (iii) preserve the
+Marvell copyright notice above.
+
+********************************************************************************
+Marvell Commercial License Option
+
+If you received this File from Marvell and you have entered into a commercial
+license agreement (a "Commercial License") with Marvell, the File is licensed
+to you under the terms of the applicable Commercial License.
+
+********************************************************************************
+Marvell GPL License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File in accordance with the terms and conditions of the General
+Public License Version 2, June 1991 (the "GPL License"), a copy of which is
+available along with the File in the license.txt file or by writing to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
+on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
+DISCLAIMED. The GPL License provides additional details about this warranty
+disclaimer.
+********************************************************************************
+Marvell BSD License Option
+
+If you received this File from Marvell, you may opt to use, redistribute and/or
+modify this File under the following licensing terms.
+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 Marvell 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.
+
+*******************************************************************************/
+
+#include "cesa/mvCesa.h"
+
+#include "ctrlEnv/mvCtrlEnvLib.h"
+#undef CESA_DEBUG
+
+
+/********** Global variables **********/
+
+/* If request size is more than MV_CESA_MAX_BUF_SIZE the
+ * request is processed as fragmented request.
+ */
+
+MV_CESA_STATS cesaStats;
+
+MV_BUF_INFO cesaSramSaBuf;
+short cesaLastSid = -1;
+MV_CESA_SA* pCesaSAD = NULL;
+MV_U16 cesaMaxSA = 0;
+
+MV_CESA_REQ* pCesaReqFirst = NULL;
+MV_CESA_REQ* pCesaReqLast = NULL;
+MV_CESA_REQ* pCesaReqEmpty = NULL;
+MV_CESA_REQ* pCesaReqProcess = NULL;
+int cesaQueueDepth = 0;
+int cesaReqResources = 0;
+
+MV_CESA_SRAM_MAP* cesaSramVirtPtr = NULL;
+MV_U32 cesaCryptEngBase = 0;
+void *cesaOsHandle = NULL;
+#if (MV_CESA_VERSION >= 3)
+MV_U32 cesaChainLength = 0;
+int chainReqNum = 0;
+MV_U32 chainIndex = 0;
+MV_CESA_REQ* pNextActiveChain = 0;
+MV_CESA_REQ* pEndCurrChain = 0;
+MV_BOOL isFirstReq = MV_TRUE;
+#endif
+
+static INLINE MV_U8* mvCesaSramAddrGet(void)
+{
+#ifdef MV_CESA_NO_SRAM
+ return (MV_U8*)cesaSramVirtPtr;
+#else
+ return (MV_U8*)cesaCryptEngBase;
+#endif /* MV_CESA_NO_SRAM */
+}
+
+static INLINE MV_ULONG mvCesaSramVirtToPhys(void* pDev, MV_U8* pSramVirt)
+{
+#ifdef MV_CESA_NO_SRAM
+ return (MV_ULONG)mvOsIoVirtToPhy(NULL, pSramVirt);
+#else
+ return (MV_ULONG)pSramVirt;
+#endif /* MV_CESA_NO_SRAM */
+}
+
+/* Internal Function prototypes */
+
+static INLINE void mvCesaSramDescrBuild(MV_U32 config, int frag,
+ int cryptoOffset, int ivOffset, int cryptoLength,
+ int macOffset, int digestOffset, int macLength, int macTotalLen,
+ MV_CESA_REQ *pCesaReq, MV_DMA_DESC* pDmaDesc);
+
+static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc);
+
+static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
+ MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
+ int offset, int copySize, MV_BOOL skipFlush);
+
+static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
+ unsigned char innerIV[], unsigned char outerIV[]);
+
+static MV_STATUS mvCesaFragAuthComplete(MV_CESA_REQ* pReq, MV_CESA_SA* pSA,
+ int macDataSize);
+
+static MV_CESA_COMMAND* mvCesaCtrModeInit(void);
+
+static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd);
+static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd);
+static void mvCesaCtrModeFinish(MV_CESA_COMMAND *pCmd);
+
+static INLINE MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq);
+static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag);
+
+static INLINE MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset);
+static INLINE MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd);
+
+static INLINE void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq,
+ int cryptoOffset, int macOffset,
+ int* pCopySize, int* pCryptoDataSize, int* pMacDataSize);
+static MV_STATUS mvCesaMbufCacheUnmap(MV_CESA_MBUF* pMbuf, int offset, int size);
+
+
+/* Go to the next request in the request queue */
+static INLINE MV_CESA_REQ* MV_CESA_REQ_NEXT_PTR(MV_CESA_REQ* pReq)
+{
+ if(pReq == pCesaReqLast)
+ return pCesaReqFirst;
+
+ return pReq+1;
+}
+
+#if (MV_CESA_VERSION >= 3)
+/* Go to the previous request in the request queue */
+static INLINE MV_CESA_REQ* MV_CESA_REQ_PREV_PTR(MV_CESA_REQ* pReq)
+{
+ if(pReq == pCesaReqFirst)
+ return pCesaReqLast;
+
+ return pReq-1;
+}
+
+#endif
+
+
+static INLINE void mvCesaReqProcessStart(MV_CESA_REQ* pReq)
+{
+ int frag;
+
+#if (MV_CESA_VERSION >= 3)
+ pReq->state = MV_CESA_CHAIN;
+#else
+ pReq->state = MV_CESA_PROCESS;
+#endif
+ cesaStats.startCount++;
+
+ if(pReq->fragMode == MV_CESA_FRAG_NONE)
+ {
+ frag = 0;
+ }
+ else
+ {
+ frag = pReq->frags.nextFrag;
+ pReq->frags.nextFrag++;
+ }
+#if (MV_CESA_VERSION >= 2)
+ /* Enable TDMA engine */
+ MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0);
+ MV_REG_WRITE(MV_CESA_TDMA_NEXT_DESC_PTR_REG,
+ (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
+#else
+ /* Enable IDMA engine */
+ MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0);
+ MV_REG_WRITE(IDMA_NEXT_DESC_PTR_REG(0),
+ (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
+#endif /* MV_CESA_VERSION >= 2 */
+
+#if defined(MV_BRIDGE_SYNC_REORDER)
+ mvOsBridgeReorderWA();
+#endif
+
+ /* Start Accelerator */
+ MV_REG_WRITE(MV_CESA_CMD_REG, MV_CESA_CMD_CHAN_ENABLE_MASK);
+}
+
+
+/*******************************************************************************
+* mvCesaHalInit - Initialize the CESA driver
+*
+* DESCRIPTION:
+* This function initialize the CESA driver.
+* 1) Session database
+* 2) Request queue
+* 4) DMA descriptor lists - one list per request. Each list
+* has MV_CESA_MAX_DMA_DESC descriptors.
+*
+* INPUT:
+* numOfSession - maximum number of supported sessions
+* queueDepth - number of elements in the request queue.
+* pSramBase - virtual address of Sram
+* osHandle - A handle used by the OS to allocate memory for the
+* module (Passed to the OS Services layer)
+*
+* RETURN:
+* MV_OK - Success
+* MV_NO_RESOURCE - Fail, can't allocate resources:
+* Session database, request queue,
+* DMA descriptors list, LRU cache database.
+* MV_NOT_ALIGNED - Sram base address is not 8 byte aligned.
+*
+*******************************************************************************/
+MV_STATUS mvCesaHalInit (int numOfSession, int queueDepth, char* pSramBase, MV_U32 cryptEngBase,
+ void *osHandle)
+{
+ int i, req;
+ MV_U32 descOffsetReg, configReg;
+ MV_CESA_SRAM_SA *pSramSA;
+
+
+ mvOsPrintf("mvCesaInit: sessions=%d, queue=%d, pSram=%p\n",
+ numOfSession, queueDepth, pSramBase);
+
+ cesaOsHandle = osHandle;
+ /* Create Session database */
+ pCesaSAD = mvOsMalloc(sizeof(MV_CESA_SA)*numOfSession);
+ if(pCesaSAD == NULL)
+ {
+ mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d SAs\n",
+ sizeof(MV_CESA_SA)*numOfSession, numOfSession);
+ mvCesaFinish();
+ return MV_NO_RESOURCE;
+ }
+ memset(pCesaSAD, 0, sizeof(MV_CESA_SA)*numOfSession);
+ cesaMaxSA = numOfSession;
+
+ /* Allocate imag of sramSA in the DRAM */
+ cesaSramSaBuf.bufSize = sizeof(MV_CESA_SRAM_SA)*numOfSession +
+ CPU_D_CACHE_LINE_SIZE;
+
+ cesaSramSaBuf.bufVirtPtr = mvOsIoCachedMalloc(osHandle,cesaSramSaBuf.bufSize,
+ &cesaSramSaBuf.bufPhysAddr,
+ &cesaSramSaBuf.memHandle);
+
+ if(cesaSramSaBuf.bufVirtPtr == NULL)
+ {
+ mvOsPrintf("mvCesaInit: Can't allocate %d bytes for sramSA structures\n",
+ cesaSramSaBuf.bufSize);
+ mvCesaFinish();
+ return MV_NO_RESOURCE;
+ }
+ memset(cesaSramSaBuf.bufVirtPtr, 0, cesaSramSaBuf.bufSize);
+ pSramSA = (MV_CESA_SRAM_SA*)MV_ALIGN_UP((MV_ULONG)cesaSramSaBuf.bufVirtPtr,
+ CPU_D_CACHE_LINE_SIZE);
+ for(i=0; i<numOfSession; i++)
+ {
+ pCesaSAD[i].pSramSA = &pSramSA[i];
+ }
+
+ /* Create request queue */
+ pCesaReqFirst = mvOsMalloc(sizeof(MV_CESA_REQ)*queueDepth);
+ if(pCesaReqFirst == NULL)
+ {
+ mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d requests\n",
+ sizeof(MV_CESA_REQ)*queueDepth, queueDepth);
+ mvCesaFinish();
+ return MV_NO_RESOURCE;
+ }
+ memset(pCesaReqFirst, 0, sizeof(MV_CESA_REQ)*queueDepth);
+ pCesaReqEmpty = pCesaReqFirst;
+ pCesaReqLast = pCesaReqFirst + (queueDepth-1);
+ pCesaReqProcess = pCesaReqEmpty;
+ cesaQueueDepth = queueDepth;
+ cesaReqResources = queueDepth;
+#if (MV_CESA_VERSION >= 3)
+ cesaChainLength = MAX_CESA_CHAIN_LENGTH;
+#endif
+ /* pSramBase must be 8 byte aligned */
+ if( MV_IS_NOT_ALIGN((MV_ULONG)pSramBase, 8) )
+ {
+ mvOsPrintf("mvCesaInit: pSramBase (%p) must be 8 byte aligned\n",
+ pSramBase);
+ mvCesaFinish();
+ return MV_NOT_ALIGNED;
+ }
+ cesaSramVirtPtr = (MV_CESA_SRAM_MAP*)pSramBase;
+
+ cesaCryptEngBase = cryptEngBase;
+
+ /*memset(cesaSramVirtPtr, 0, sizeof(MV_CESA_SRAM_MAP));*/
+
+ /* Clear registers */
+ MV_REG_WRITE( MV_CESA_CFG_REG, 0);
+ MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
+ MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
+
+ /* Initialize DMA descriptor lists for all requests in Request queue */
+ descOffsetReg = configReg = 0;
+ for(req=0; req<queueDepth; req++)
+ {
+ int frag;
+ MV_CESA_REQ* pReq;
+ MV_DMA_DESC* pDmaDesc;
+
+ pReq = &pCesaReqFirst[req];
+
+ pReq->cesaDescBuf.bufSize = sizeof(MV_CESA_DESC)*MV_CESA_MAX_REQ_FRAGS +
+ CPU_D_CACHE_LINE_SIZE;
+
+ pReq->cesaDescBuf.bufVirtPtr =
+ mvOsIoCachedMalloc(osHandle,pReq->cesaDescBuf.bufSize,
+ &pReq->cesaDescBuf.bufPhysAddr,
+ &pReq->cesaDescBuf.memHandle);
+
+ if(pReq->cesaDescBuf.bufVirtPtr == NULL)
+ {
+ mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for CESA descriptors\n",
+ req, pReq->cesaDescBuf.bufSize);
+ mvCesaFinish();
+ return MV_NO_RESOURCE;
+ }
+ memset(pReq->cesaDescBuf.bufVirtPtr, 0, pReq->cesaDescBuf.bufSize);
+ pReq->pCesaDesc = (MV_CESA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->cesaDescBuf.bufVirtPtr,
+ CPU_D_CACHE_LINE_SIZE);
+
+ pReq->dmaDescBuf.bufSize = sizeof(MV_DMA_DESC)*MV_CESA_MAX_DMA_DESC*MV_CESA_MAX_REQ_FRAGS +
+ CPU_D_CACHE_LINE_SIZE;
+
+ pReq->dmaDescBuf.bufVirtPtr =
+ mvOsIoCachedMalloc(osHandle,pReq->dmaDescBuf.bufSize,
+ &pReq->dmaDescBuf.bufPhysAddr,
+ &pReq->dmaDescBuf.memHandle);
+
+ if(pReq->dmaDescBuf.bufVirtPtr == NULL)
+ {
+ mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for DMA descriptor list\n",
+ req, pReq->dmaDescBuf.bufSize);
+ mvCesaFinish();
+ return MV_NO_RESOURCE;
+ }
+ memset(pReq->dmaDescBuf.bufVirtPtr, 0, pReq->dmaDescBuf.bufSize);
+ pDmaDesc = (MV_DMA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->dmaDescBuf.bufVirtPtr,
+ CPU_D_CACHE_LINE_SIZE);
+
+ for(frag=0; frag<MV_CESA_MAX_REQ_FRAGS; frag++)
+ {
+ MV_CESA_DMA* pDma = &pReq->dma[frag];
+
+ pDma->pDmaFirst = pDmaDesc;
+ pDma->pDmaLast = NULL;
+
+ for(i=0; i<MV_CESA_MAX_DMA_DESC-1; i++)
+ {
+ /* link all DMA descriptors together */
+ pDma->pDmaFirst[i].phyNextDescPtr =
+ MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pDmaDesc[i+1]));
+ }
+ pDma->pDmaFirst[i].phyNextDescPtr = 0;
+ mvOsCacheFlush(NULL, &pDma->pDmaFirst[0], MV_CESA_MAX_DMA_DESC*sizeof(MV_DMA_DESC));
+
+ pDmaDesc += MV_CESA_MAX_DMA_DESC;
+ }
+ }
+ /*mvCesaCryptoIvSet(NULL, MV_CESA_MAX_IV_LENGTH);*/
+ descOffsetReg = (MV_U16)((MV_U8*)&cesaSramVirtPtr->desc - mvCesaSramAddrGet());
+ MV_REG_WRITE(MV_CESA_CHAN_DESC_OFFSET_REG, descOffsetReg);
+
+ configReg |= (MV_CESA_CFG_WAIT_DMA_MASK | MV_CESA_CFG_ACT_DMA_MASK);
+#if (MV_CESA_VERSION >= 3)
+ configReg |= MV_CESA_CFG_CHAIN_MODE_MASK;
+#endif
+
+#if (MV_CESA_VERSION >= 2)
+ /* Initialize TDMA engine */
+ MV_REG_WRITE(MV_CESA_TDMA_CTRL_REG, MV_CESA_TDMA_CTRL_VALUE);
+ MV_REG_WRITE(MV_CESA_TDMA_BYTE_COUNT_REG, 0);
+ MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0);
+#else
+ /* Initialize IDMA #0 engine */
+ MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0);
+ MV_REG_WRITE(IDMA_BYTE_COUNT_REG(0), 0);
+ MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0);
+ MV_REG_WRITE(IDMA_CTRL_HIGH_REG(0), ICCHR_ENDIAN_LITTLE
+#ifdef MV_CPU_LE
+ | ICCHR_DESC_BYTE_SWAP_EN
+#endif
+ );
+ /* Clear Cause Byte of IDMA channel to be used */
+ MV_REG_WRITE( IDMA_CAUSE_REG, ~ICICR_CAUSE_MASK_ALL(0));
+ MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), MV_CESA_IDMA_CTRL_LOW_VALUE);
+#endif /* (MV_CESA_VERSION >= 2) */
+
+ /* Set CESA configuration registers */
+ MV_REG_WRITE( MV_CESA_CFG_REG, configReg);
+ mvCesaDebugStatsClear();
+
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaFinish - Shutdown the CESA driver
+*
+* DESCRIPTION:
+* This function shutdown the CESA driver and free all allocted resources.
+*
+* INPUT: None
+*
+* RETURN:
+* MV_OK - Success
+* Other - Fail
+*
+*******************************************************************************/
+MV_STATUS mvCesaFinish (void)
+{
+ int req;
+ MV_CESA_REQ* pReq;
+
+ mvOsPrintf("mvCesaFinish: \n");
+
+ cesaSramVirtPtr = NULL;
+
+ /* Free all resources: DMA list, etc. */
+ for(req=0; req<cesaQueueDepth; req++)
+ {
+ pReq = &pCesaReqFirst[req];
+ if(pReq->dmaDescBuf.bufVirtPtr != NULL)
+ {
+ mvOsIoCachedFree(cesaOsHandle,pReq->dmaDescBuf.bufSize,
+ pReq->dmaDescBuf.bufPhysAddr,
+ pReq->dmaDescBuf.bufVirtPtr,
+ pReq->dmaDescBuf.memHandle);
+ }
+ if(pReq->cesaDescBuf.bufVirtPtr != NULL)
+ {
+ mvOsIoCachedFree(cesaOsHandle,pReq->cesaDescBuf.bufSize,
+ pReq->cesaDescBuf.bufPhysAddr,
+ pReq->cesaDescBuf.bufVirtPtr,
+ pReq->cesaDescBuf.memHandle);
+ }
+ }
+#if (MV_CESA_VERSION < 2)
+ MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0);
+#endif /* (MV_CESA_VERSION < 2) */
+
+ /* Free request queue */
+ if(pCesaReqFirst != NULL)
+ {
+ mvOsFree(pCesaReqFirst);
+ pCesaReqFirst = pCesaReqLast = NULL;
+ pCesaReqEmpty = pCesaReqProcess = NULL;
+ cesaQueueDepth = cesaReqResources = 0;
+ }
+ /* Free SA database */
+ if(pCesaSAD != NULL)
+ {
+ mvOsFree(pCesaSAD);
+ pCesaSAD = NULL;
+ cesaMaxSA = 0;
+ }
+ MV_REG_WRITE( MV_CESA_CFG_REG, 0);
+ MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
+ MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
+
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaCryptoIvSet - Set IV value for Crypto algorithm working in CBC mode
+*
+* DESCRIPTION:
+* This function set IV value using by Crypto algorithms in CBC mode.
+* Each channel has its own IV value.
+* This function gets IV value from the caller. If no IV value passed from
+* the caller or only part of IV passed, the function will init the rest part
+* of IV value (or the whole IV) by random value.
+*
+* INPUT:
+* MV_U8* pIV - Pointer to IV value supplied by user. If pIV==NULL
+* the function will generate random IV value.
+* int ivSize - size (in bytes) of IV provided by user. If ivSize is
+* smaller than maximum IV size, the function will complete
+* IV by random value.
+*
+* RETURN:
+* MV_OK - Success
+* Other - Fail
+*
+*******************************************************************************/
+MV_STATUS mvCesaCryptoIvSet(MV_U8* pIV, int ivSize)
+{
+ MV_U8* pSramIV;
+#if defined(MV646xx)
+ mvOsPrintf("mvCesaCryptoIvSet: ERR. shouldn't use this call on MV64660\n");
+#endif
+ pSramIV = cesaSramVirtPtr->cryptoIV;
+ if(ivSize > MV_CESA_MAX_IV_LENGTH)
+ {
+ mvOsPrintf("mvCesaCryptoIvSet: ivSize (%d) is too large\n", ivSize);
+ ivSize = MV_CESA_MAX_IV_LENGTH;
+ }
+ if(pIV != NULL)
+ {
+ memcpy(pSramIV, pIV, ivSize);
+ ivSize = MV_CESA_MAX_IV_LENGTH - ivSize;
+ pSramIV += ivSize;
+ }
+
+ while(ivSize > 0)
+ {
+ int size, mv_random = mvOsRand();
+
+ size = MV_MIN(ivSize, sizeof(mv_random));
+ memcpy(pSramIV, (void*)&mv_random, size);
+
+ pSramIV += size;
+ ivSize -= size;
+ }
+/*
+ mvOsCacheFlush(NULL, cesaSramVirtPtr->cryptoIV,
+ MV_CESA_MAX_IV_LENGTH);
+ mvOsCacheInvalidate(NULL, cesaSramVirtPtr->cryptoIV,
+ MV_CESA_MAX_IV_LENGTH);
+*/
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaSessionOpen - Open new uni-directional crypto session
+*
+* DESCRIPTION:
+* This function open new session.
+*
+* INPUT:
+* MV_CESA_OPEN_SESSION *pSession - pointer to new session input parameters
+*
+* OUTPUT:
+* short *pSid - session ID, should be used for all future
+* requests over this session.
+*
+* RETURN:
+* MV_OK - Session opend successfully.
+* MV_FULL - All sessions are in use, no free place in
+* SA database.
+* MV_BAD_PARAM - One of session input parameters is invalid.
+*
+*******************************************************************************/
+MV_STATUS mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short* pSid)
+{
+ short sid;
+ MV_U32 config = 0;
+ int digestSize;
+
+ cesaStats.openedCount++;
+
+ /* Find free entry in SAD */
+ for(sid=0; sid<cesaMaxSA; sid++)
+ {
+ if(pCesaSAD[sid].valid == 0)
+ {
+ break;
+ }
+ }
+ if(sid == cesaMaxSA)
+ {
+ mvOsPrintf("mvCesaSessionOpen: SA Database is FULL\n");
+ return MV_FULL;
+ }
+
+ /* Check Input parameters for Open session */
+ if (pSession->operation >= MV_CESA_MAX_OPERATION)
+ {
+ mvOsPrintf("mvCesaSessionOpen: Unexpected operation %d\n",
+ pSession->operation);
+ return MV_BAD_PARAM;
+ }
+ config |= (pSession->operation << MV_CESA_OPERATION_OFFSET);
+
+ if( (pSession->direction != MV_CESA_DIR_ENCODE) &&
+ (pSession->direction != MV_CESA_DIR_DECODE) )
+ {
+ mvOsPrintf("mvCesaSessionOpen: Unexpected direction %d\n",
+ pSession->direction);
+ return MV_BAD_PARAM;
+ }
+ config |= (pSession->direction << MV_CESA_DIRECTION_BIT);
+ /* Clear SA entry */
+ /* memset(&pCesaSAD[sid], 0, sizeof(pCesaSAD[sid])); */
+
+ /* Check AUTH parameters and update SA entry */
+ if(pSession->operation != MV_CESA_CRYPTO_ONLY)
+ {
+ /* For HMAC (MD5 and SHA1) - Maximum Key size is 64 bytes */
+ if( (pSession->macMode == MV_CESA_MAC_HMAC_MD5) ||
+ (pSession->macMode == MV_CESA_MAC_HMAC_SHA1) )
+ {
+ if(pSession->macKeyLength > MV_CESA_MAX_MAC_KEY_LENGTH)
+ {
+ mvOsPrintf("mvCesaSessionOpen: macKeyLength %d is too large\n",
+ pSession->macKeyLength);
+ return MV_BAD_PARAM;
+ }
+ mvCesaHmacIvGet(pSession->macMode, pSession->macKey, pSession->macKeyLength,
+ pCesaSAD[sid].pSramSA->macInnerIV,
+ pCesaSAD[sid].pSramSA->macOuterIV);
+ pCesaSAD[sid].macKeyLength = pSession->macKeyLength;
+ }
+ switch(pSession->macMode)
+ {
+ case MV_CESA_MAC_MD5:
+ case MV_CESA_MAC_HMAC_MD5:
+ digestSize = MV_CESA_MD5_DIGEST_SIZE;
+ break;
+
+ case MV_CESA_MAC_SHA1:
+ case MV_CESA_MAC_HMAC_SHA1:
+ digestSize = MV_CESA_SHA1_DIGEST_SIZE;
+ break;
+
+ default:
+ mvOsPrintf("mvCesaSessionOpen: Unexpected macMode %d\n",
+ pSession->macMode);
+ return MV_BAD_PARAM;
+ }
+ config |= (pSession->macMode << MV_CESA_MAC_MODE_OFFSET);
+
+ /* Supported digest sizes: MD5 - 16 bytes (128 bits), */
+ /* SHA1 - 20 bytes (160 bits) or 12 bytes (96 bits) for both */
+ if( (pSession->digestSize != digestSize) && (pSession->digestSize != 12))
+ {
+ mvOsPrintf("mvCesaSessionOpen: Unexpected digest size %d\n",
+ pSession->digestSize);
+ mvOsPrintf("\t Valid values [bytes]: MD5-16, SHA1-20, Both-12\n");
+ return MV_BAD_PARAM;
+ }
+ pCesaSAD[sid].digestSize = pSession->digestSize;
+
+ if(pCesaSAD[sid].digestSize == 12)
+ {
+ /* Set MV_CESA_MAC_DIGEST_SIZE_BIT if digest size is 96 bits */
+ config |= (MV_CESA_MAC_DIGEST_96B << MV_CESA_MAC_DIGEST_SIZE_BIT);
+ }
+ }
+
+ /* Check CRYPTO parameters and update SA entry */
+ if(pSession->operation != MV_CESA_MAC_ONLY)
+ {
+ switch(pSession->cryptoAlgorithm)
+ {
+ case MV_CESA_CRYPTO_DES:
+ pCesaSAD[sid].cryptoKeyLength = MV_CESA_DES_KEY_LENGTH;
+ pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE;
+ break;
+
+ case MV_CESA_CRYPTO_3DES:
+ pCesaSAD[sid].cryptoKeyLength = MV_CESA_3DES_KEY_LENGTH;
+ pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE;
+ /* Only EDE mode is supported */
+ config |= (MV_CESA_CRYPTO_3DES_EDE <<
+ MV_CESA_CRYPTO_3DES_MODE_BIT);
+ break;
+
+ case MV_CESA_CRYPTO_AES:
+ switch(pSession->cryptoKeyLength)
+ {
+ case 16:
+ pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_128_KEY_LENGTH;
+ config |= (MV_CESA_CRYPTO_AES_KEY_128 <<
+ MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
+ break;
+
+ case 24:
+ pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_192_KEY_LENGTH;
+ config |= (MV_CESA_CRYPTO_AES_KEY_192 <<
+ MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
+ break;
+
+ case 32:
+ default:
+ pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_256_KEY_LENGTH;
+ config |= (MV_CESA_CRYPTO_AES_KEY_256 <<
+ MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
+ break;
+ }
+ pCesaSAD[sid].cryptoBlockSize = MV_CESA_AES_BLOCK_SIZE;
+ break;
+
+ default:
+ mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoAlgorithm %d\n",
+ pSession->cryptoAlgorithm);
+ return MV_BAD_PARAM;
+ }
+ config |= (pSession->cryptoAlgorithm << MV_CESA_CRYPTO_ALG_OFFSET);
+
+ if(pSession->cryptoKeyLength != pCesaSAD[sid].cryptoKeyLength)
+ {
+ mvOsPrintf("cesaSessionOpen: Wrong CryptoKeySize %d != %d\n",
+ pSession->cryptoKeyLength, pCesaSAD[sid].cryptoKeyLength);
+ return MV_BAD_PARAM;
+ }
+
+ /* Copy Crypto key */
+ if( (pSession->cryptoAlgorithm == MV_CESA_CRYPTO_AES) &&
+ (pSession->direction == MV_CESA_DIR_DECODE))
+ {
+ /* Crypto Key for AES decode is computed from original key material */
+ /* and depend on cryptoKeyLength (128/192/256 bits) */
+ aesMakeKey(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey,
+ pSession->cryptoKeyLength*8, MV_CESA_AES_BLOCK_SIZE*8);
+ }
+ else
+ {
+ /*panic("mvCesaSessionOpen2");*/
+ memcpy(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey,
+ pCesaSAD[sid].cryptoKeyLength);
+
+ }
+
+ switch(pSession->cryptoMode)
+ {
+ case MV_CESA_CRYPTO_ECB:
+ pCesaSAD[sid].cryptoIvSize = 0;
+ break;
+
+ case MV_CESA_CRYPTO_CBC:
+ pCesaSAD[sid].cryptoIvSize = pCesaSAD[sid].cryptoBlockSize;
+ break;
+
+ case MV_CESA_CRYPTO_CTR:
+ /* Supported only for AES algorithm */
+ if(pSession->cryptoAlgorithm != MV_CESA_CRYPTO_AES)
+ {
+ mvOsPrintf("mvCesaSessionOpen: CRYPTO CTR mode supported for AES only\n");
+ return MV_BAD_PARAM;
+ }
+ pCesaSAD[sid].cryptoIvSize = 0;
+ pCesaSAD[sid].ctrMode = 1;
+ /* Replace to ECB mode for HW */
+ pSession->cryptoMode = MV_CESA_CRYPTO_ECB;
+ break;
+
+ default:
+ mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoMode %d\n",
+ pSession->cryptoMode);
+ return MV_BAD_PARAM;
+ }
+
+ config |= (pSession->cryptoMode << MV_CESA_CRYPTO_MODE_BIT);
+ }
+ pCesaSAD[sid].config = config;
+
+ mvOsCacheFlush(NULL, pCesaSAD[sid].pSramSA, sizeof(MV_CESA_SRAM_SA));
+ if(pSid != NULL)
+ *pSid = sid;
+
+ pCesaSAD[sid].valid = 1;
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaSessionClose - Close active crypto session
+*
+* DESCRIPTION:
+* This function closes existing session
+*
+* INPUT:
+* short sid - Unique identifier of the session to be closed
+*
+* RETURN:
+* MV_OK - Session closed successfully.
+* MV_BAD_PARAM - Session identifier is out of valid range.
+* MV_NOT_FOUND - There is no active session with such ID.
+*
+*******************************************************************************/
+MV_STATUS mvCesaSessionClose(short sid)
+{
+ cesaStats.closedCount++;
+
+ if(sid >= cesaMaxSA)
+ {
+ mvOsPrintf("CESA Error: sid (%d) is too big\n", sid);
+ return MV_BAD_PARAM;
+ }
+ if(pCesaSAD[sid].valid == 0)
+ {
+ mvOsPrintf("CESA Warning: Session (sid=%d) is invalid\n", sid);
+ return MV_NOT_FOUND;
+ }
+ if(cesaLastSid == sid)
+ cesaLastSid = -1;
+
+ pCesaSAD[sid].valid = 0;
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaAction - Perform crypto operation
+*
+* DESCRIPTION:
+* This function set new CESA request FIFO queue for further HW processing.
+* The function checks request parameters before set new request to the queue.
+* If one of the CESA channels is ready for processing the request will be
+* passed to HW. When request processing is finished the CESA interrupt will
+* be generated by HW. The caller should call mvCesaReadyGet() function to
+* complete request processing and get result.
+*
+* INPUT:
+* MV_CESA_COMMAND *pCmd - pointer to new CESA request.
+* It includes pointers to Source and Destination
+* buffers, session identifier get from
+* mvCesaSessionOpen() function, pointer to caller
+* private data and all needed crypto parameters.
+*
+* RETURN:
+* MV_OK - request successfully added to request queue
+* and will be processed.
+* MV_NO_MORE - request successfully added to request queue and will
+* be processed, but request queue became Full and next
+* request will not be accepted.
+* MV_NO_RESOURCE - request queue is FULL and the request can not
+* be processed.
+* MV_OUT_OF_CPU_MEM - memory allocation needed for request processing is
+* failed. Request can not be processed.
+* MV_NOT_ALLOWED - This mixed request (CRYPTO+MAC) can not be processed
+* as one request and should be splitted for two requests:
+* CRYPTO_ONLY and MAC_ONLY.
+* MV_BAD_PARAM - One of the request parameters is out of valid range.
+* The request can not be processed.
+*
+*******************************************************************************/
+MV_STATUS mvCesaAction (MV_CESA_COMMAND *pCmd)
+{
+ MV_STATUS status;
+ MV_CESA_REQ* pReq = pCesaReqEmpty;
+ int sid = pCmd->sessionId;
+ MV_CESA_SA* pSA = &pCesaSAD[sid];
+#if (MV_CESA_VERSION >= 3)
+ MV_CESA_REQ* pFromReq;
+ MV_CESA_REQ* pToReq;
+#endif
+ cesaStats.reqCount++;
+
+ /* Check that the request queue is not FULL */
+ if(cesaReqResources == 0)
+ return MV_NO_RESOURCE;
+
+ if( (sid >= cesaMaxSA) || (!pSA->valid) )
+ {
+ mvOsPrintf("CESA Action Error: Session sid=%d is INVALID\n", sid);
+ return MV_BAD_PARAM;
+ }
+ pSA->count++;
+
+ if(pSA->ctrMode)
+ {
+ /* AES in CTR mode can't be mixed with Authentication */
+ if( (pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ mvOsPrintf("mvCesaAction : CRYPTO CTR mode can't be mixed with AUTH\n");
+ return MV_NOT_ALLOWED;
+ }
+ /* All other request parameters should not be checked because key stream */
+ /* (not user data) processed by AES HW engine */
+ pReq->pOrgCmd = pCmd;
+ /* Allocate temporary pCmd structure for Key stream */
+ pCmd = mvCesaCtrModeInit();
+ if(pCmd == NULL)
+ return MV_OUT_OF_CPU_MEM;
+
+ /* Prepare Key stream */
+ mvCesaCtrModePrepare(pCmd, pReq->pOrgCmd);
+ pReq->fixOffset = 0;
+ }
+ else
+ {
+ /* Check request parameters and calculae fixOffset */
+ status = mvCesaParamCheck(pSA, pCmd, &pReq->fixOffset);
+ if(status != MV_OK)
+ {
+ return status;
+ }
+ }
+ pReq->pCmd = pCmd;
+
+ /* Check if the packet need fragmentation */
+ if(pCmd->pSrc->mbufSize <= sizeof(cesaSramVirtPtr->buf) )
+ {
+ /* request size is smaller than single buffer size */
+ pReq->fragMode = MV_CESA_FRAG_NONE;
+
+ /* Prepare NOT fragmented packets */
+ status = mvCesaReqProcess(pReq);
+ if(status != MV_OK)
+ {
+ mvOsPrintf("CesaReady: ReqProcess error: pReq=%p, status=0x%x\n",
+ pReq, status);
+ }
+#if (MV_CESA_VERSION >= 3)
+ pReq->frags.numFrag = 1;
+#endif
+ }
+ else
+ {
+ MV_U8 frag = 0;
+
+ /* request size is larger than buffer size - needs fragmentation */
+
+ /* Check restrictions for processing fragmented packets */
+ status = mvCesaFragParamCheck(pSA, pCmd);
+ if(status != MV_OK)
+ return status;
+
+ pReq->fragMode = MV_CESA_FRAG_FIRST;
+ pReq->frags.nextFrag = 0;
+
+ /* Prepare Process Fragmented packets */
+ while(pReq->fragMode != MV_CESA_FRAG_LAST)
+ {
+ if(frag >= MV_CESA_MAX_REQ_FRAGS)
+ {
+ mvOsPrintf("mvCesaAction Error: Too large request frag=%d\n", frag);
+ return MV_OUT_OF_CPU_MEM;
+ }
+ status = mvCesaFragReqProcess(pReq, frag);
+ if(status == MV_OK) {
+#if (MV_CESA_VERSION >= 3)
+ if(frag) {
+ pReq->dma[frag-1].pDmaLast->phyNextDescPtr =
+ MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
+ mvOsCacheFlush(NULL, pReq->dma[frag-1].pDmaLast, sizeof(MV_DMA_DESC));
+ }
+#endif
+ frag++;
+ }
+ }
+ pReq->frags.numFrag = frag;
+#if (MV_CESA_VERSION >= 3)
+ if(chainReqNum) {
+ chainReqNum += pReq->frags.numFrag;
+ if(chainReqNum >= MAX_CESA_CHAIN_LENGTH)
+ chainReqNum = MAX_CESA_CHAIN_LENGTH;
+ }
+#endif
+ }
+
+ pReq->state = MV_CESA_PENDING;
+
+ pCesaReqEmpty = MV_CESA_REQ_NEXT_PTR(pReq);
+ cesaReqResources -= 1;
+
+/* #ifdef CESA_DEBUG */
+ if( (cesaQueueDepth - cesaReqResources) > cesaStats.maxReqCount)
+ cesaStats.maxReqCount = (cesaQueueDepth - cesaReqResources);
+/* #endif CESA_DEBUG */
+
+ cesaLastSid = sid;
+
+#if (MV_CESA_VERSION >= 3)
+ /* Are we within chain bounderies and follows the first request ? */
+ if((chainReqNum > 0) && (chainReqNum < MAX_CESA_CHAIN_LENGTH)) {
+ if(chainIndex) {
+ pFromReq = MV_CESA_REQ_PREV_PTR(pReq);
+ pToReq = pReq;
+ pReq->state = MV_CESA_CHAIN;
+ /* assume concatenating is possible */
+ pFromReq->dma[pFromReq->frags.numFrag-1].pDmaLast->phyNextDescPtr =
+ MV_32BIT_LE(mvCesaVirtToPhys(&pToReq->dmaDescBuf, pToReq->dma[0].pDmaFirst));
+ mvOsCacheFlush(NULL, pFromReq->dma[pFromReq->frags.numFrag-1].pDmaLast, sizeof(MV_DMA_DESC));
+
+ /* align active & next pointers */
+ if(pNextActiveChain->state != MV_CESA_PENDING)
+ pEndCurrChain = pNextActiveChain = MV_CESA_REQ_NEXT_PTR(pReq);
+ }
+ else { /* we have only one chain, start new one */
+ chainReqNum = 0;
+ chainIndex++;
+ /* align active & next pointers */
+ if(pNextActiveChain->state != MV_CESA_PENDING)
+ pEndCurrChain = pNextActiveChain = pReq;
+ }
+ }
+ else {
+ /* In case we concatenate full chain */
+ if(chainReqNum == MAX_CESA_CHAIN_LENGTH) {
+ chainIndex++;
+ if(pNextActiveChain->state != MV_CESA_PENDING)
+ pEndCurrChain = pNextActiveChain = pReq;
+ chainReqNum = 0;
+ }
+
+ pReq = pCesaReqProcess;
+ if(pReq->state == MV_CESA_PENDING) {
+ pNextActiveChain = pReq;
+ pEndCurrChain = MV_CESA_REQ_NEXT_PTR(pReq);
+ /* Start Process new request */
+ mvCesaReqProcessStart(pReq);
+ }
+ }
+
+ chainReqNum++;
+
+ if((chainIndex < MAX_CESA_CHAIN_LENGTH) && (chainReqNum > cesaStats.maxChainUsage))
+ cesaStats.maxChainUsage = chainReqNum;
+
+#else
+
+ /* Check status of CESA channels and process requests if possible */
+ pReq = pCesaReqProcess;
+ if(pReq->state == MV_CESA_PENDING)
+ {
+ /* Start Process new request */
+ mvCesaReqProcessStart(pReq);
+ }
+#endif
+ /* If request queue became FULL - return MV_NO_MORE */
+ if(cesaReqResources == 0)
+ return MV_NO_MORE;
+
+ return MV_OK;
+
+}
+
+/*******************************************************************************
+* mvCesaReadyGet - Get crypto request that processing is finished
+*
+* DESCRIPTION:
+* This function complete request processing and return ready request to
+* caller. To don't miss interrupts the caller must call this function
+* while MV_OK or MV_TERMINATE values returned.
+*
+* INPUT:
+* MV_U32 chanMap - map of CESA channels finished thier job
+* accordingly with CESA Cause register.
+* MV_CESA_RESULT* pResult - pointer to structure contains information
+* about ready request. It includes pointer to
+* user private structure "pReqPrv", session identifier
+* for this request "sessionId" and return code.
+* Return code set to MV_FAIL if calculated digest value
+* on decode direction is different than digest value
+* in the packet.
+*
+* RETURN:
+* MV_OK - Success, ready request is returned.
+* MV_NOT_READY - Next request is not ready yet. New interrupt will
+* be generated for futher request processing.
+* MV_EMPTY - There is no more request for processing.
+* MV_BUSY - Fragmented request is not ready yet.
+* MV_TERMINATE - Call this function once more to complete processing
+* of fragmented request.
+*
+*******************************************************************************/
+MV_STATUS mvCesaReadyGet(MV_CESA_RESULT* pResult)
+{
+ MV_STATUS status, readyStatus = MV_NOT_READY;
+ MV_U32 statusReg;
+ MV_CESA_REQ* pReq;
+ MV_CESA_SA* pSA;
+
+#if (MV_CESA_VERSION >= 3)
+ if(isFirstReq == MV_TRUE) {
+ if(chainIndex == 0)
+ chainReqNum = 0;
+
+ isFirstReq = MV_FALSE;
+
+ if(pNextActiveChain->state == MV_CESA_PENDING) {
+ /* Start request Process */
+ mvCesaReqProcessStart(pNextActiveChain);
+ pEndCurrChain = pNextActiveChain;
+ if(chainIndex > 0)
+ chainIndex--;
+ /* Update pNextActiveChain to next chain head */
+ while(pNextActiveChain->state == MV_CESA_CHAIN)
+ pNextActiveChain = MV_CESA_REQ_NEXT_PTR(pNextActiveChain);
+ }
+ }
+
+ /* Check if there are more processed requests - can we remove pEndCurrChain ??? */
+ if(pCesaReqProcess == pEndCurrChain) {
+ isFirstReq = MV_TRUE;
+ pEndCurrChain = pNextActiveChain;
+#else
+ if(pCesaReqProcess->state != MV_CESA_PROCESS) {
+#endif
+ return MV_EMPTY;
+ }
+
+#ifdef CESA_DEBUG
+ statusReg = MV_REG_READ(MV_CESA_STATUS_REG);
+ if( statusReg & MV_CESA_STATUS_ACTIVE_MASK )
+ {
+ mvOsPrintf("mvCesaReadyGet: Not Ready, Status = 0x%x\n", statusReg);
+ cesaStats.notReadyCount++;
+ return MV_NOT_READY;
+ }
+#endif /* CESA_DEBUG */
+
+ cesaStats.readyCount++;
+
+ pReq = pCesaReqProcess;
+ pSA = &pCesaSAD[pReq->pCmd->sessionId];
+
+ pResult->retCode = MV_OK;
+ if(pReq->fragMode != MV_CESA_FRAG_NONE)
+ {
+ MV_U8* pNewDigest;
+ int frag;
+#if (MV_CESA_VERSION >= 3)
+ pReq->frags.nextFrag = 1;
+ while(pReq->frags.nextFrag <= pReq->frags.numFrag) {
+#endif
+ frag = (pReq->frags.nextFrag - 1);
+
+ /* Restore DMA descriptor list */
+ pReq->dma[frag].pDmaLast->phyNextDescPtr =
+ MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[frag].pDmaLast[1]));
+ pReq->dma[frag].pDmaLast = NULL;
+
+ /* Special processing for finished fragmented request */
+ if(pReq->frags.nextFrag >= pReq->frags.numFrag)
+ {
+ mvCesaMbufCacheUnmap(pReq->pCmd->pDst, 0, pReq->pCmd->pDst->mbufSize);
+
+ /* Fragmented packet is ready */
+ if( (pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ int macDataSize = pReq->pCmd->macLength - pReq->frags.macSize;
+
+ if(macDataSize != 0)
+ {
+ /* Calculate all other blocks by SW */
+ mvCesaFragAuthComplete(pReq, pSA, macDataSize);
+ }
+
+ /* Copy new digest from SRAM to the Destination buffer */
+ pNewDigest = cesaSramVirtPtr->buf + pReq->frags.newDigestOffset;
+ status = mvCesaCopyToMbuf(pNewDigest, pReq->pCmd->pDst,
+ pReq->pCmd->digestOffset, pSA->digestSize);
+
+ /* For decryption: Compare new digest value with original one */
+ if((pSA->config & MV_CESA_DIRECTION_MASK) ==
+ (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
+ {
+ if( memcmp(pNewDigest, pReq->frags.orgDigest, pSA->digestSize) != 0)
+ {
+/*
+ mvOsPrintf("Digest error: chan=%d, newDigest=%p, orgDigest=%p, status = 0x%x\n",
+ chan, pNewDigest, pReq->frags.orgDigest, MV_REG_READ(MV_CESA_STATUS_REG));
+*/
+ /* Signiture verification is failed */
+ pResult->retCode = MV_FAIL;
+ }
+ }
+ }
+ readyStatus = MV_OK;
+ }
+#if (MV_CESA_VERSION >= 3)
+ pReq->frags.nextFrag++;
+ }
+#endif
+ }
+ else
+ {
+ mvCesaMbufCacheUnmap(pReq->pCmd->pDst, 0, pReq->pCmd->pDst->mbufSize);
+
+ /* Restore DMA descriptor list */
+ pReq->dma[0].pDmaLast->phyNextDescPtr =
+ MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[0].pDmaLast[1]));
+ pReq->dma[0].pDmaLast = NULL;
+ if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) &&
+ ((pSA->config & MV_CESA_DIRECTION_MASK) ==
+ (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) )
+ {
+ /* For AUTH on decode : Check Digest result in Status register */
+ statusReg = MV_REG_READ(MV_CESA_STATUS_REG);
+ if(statusReg & MV_CESA_STATUS_DIGEST_ERR_MASK)
+ {
+/*
+ mvOsPrintf("Digest error: chan=%d, status = 0x%x\n",
+ chan, statusReg);
+*/
+ /* Signiture verification is failed */
+ pResult->retCode = MV_FAIL;
+ }
+ }
+ readyStatus = MV_OK;
+ }
+
+ if(readyStatus == MV_OK)
+ {
+ /* If Request is ready - Prepare pResult structure */
+ pResult->pReqPrv = pReq->pCmd->pReqPrv;
+ pResult->sessionId = pReq->pCmd->sessionId;
+
+ pReq->state = MV_CESA_IDLE;
+ pCesaReqProcess = MV_CESA_REQ_NEXT_PTR(pReq);
+ cesaReqResources++;
+
+ if(pSA->ctrMode)
+ {
+ /* For AES CTR mode - complete processing and free allocated resources */
+ mvCesaCtrModeComplete(pReq->pOrgCmd, pReq->pCmd);
+ mvCesaCtrModeFinish(pReq->pCmd);
+ pReq->pOrgCmd = NULL;
+ }
+ }
+
+#if (MV_CESA_VERSION < 3)
+ if(pCesaReqProcess->state == MV_CESA_PROCESS)
+ {
+ /* Start request Process */
+ mvCesaReqProcessStart(pCesaReqProcess);
+ if(readyStatus == MV_NOT_READY)
+ readyStatus = MV_BUSY;
+ }
+ else if(pCesaReqProcess != pCesaReqEmpty)
+ {
+ /* Start process new request from the queue */
+ mvCesaReqProcessStart(pCesaReqProcess);
+ }
+#endif
+ return readyStatus;
+}
+
+/***************** Functions to work with CESA_MBUF structure ******************/
+
+/*******************************************************************************
+* mvCesaMbufOffset - Locate offset in the Mbuf structure
+*
+* DESCRIPTION:
+* This function locates offset inside Multi-Bufeer structure.
+* It get fragment number and place in the fragment where the offset
+* is located.
+*
+*
+* INPUT:
+* MV_CESA_MBUF* pMbuf - Pointer to multi-buffer structure
+* int offset - Offset from the beginning of the data presented by
+* the Mbuf structure.
+*
+* OUTPUT:
+* int* pBufOffset - Offset from the beginning of the fragment where
+* the offset is located.
+*
+* RETURN:
+* int - Number of fragment, where the offset is located\
+*
+*******************************************************************************/
+int mvCesaMbufOffset(MV_CESA_MBUF* pMbuf, int offset, int* pBufOffset)
+{
+ int frag = 0;
+
+ while(offset > 0)
+ {
+ if(frag >= pMbuf->numFrags)
+ {
+ mvOsPrintf("mvCesaMbufOffset: Error: frag (%d) > numFrags (%d)\n",
+ frag, pMbuf->numFrags);
+ return MV_INVALID;
+ }
+ if(offset < pMbuf->pFrags[frag].bufSize)
+ {
+ break;
+ }
+ offset -= pMbuf->pFrags[frag].bufSize;
+ frag++;
+ }
+ if(pBufOffset != NULL)
+ *pBufOffset = offset;
+
+ return frag;
+}
+
+/*******************************************************************************
+* mvCesaCopyFromMbuf - Copy data from the Mbuf structure to continuous buffer
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_U8* pDstBuf - Pointer to continuous buffer, where data is
+* copied to.
+* MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is
+* copied from.
+* int offset - Offset in the Mbuf structure where located first
+* byte of data should be copied.
+* int size - Size of data should be copied
+*
+* RETURN:
+* MV_OK - Success, all data is copied successfully.
+* MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range.
+* No data is copied.
+* MV_EMPTY - Multi-buffer structure has not enough data to copy
+* Data from the offset to end of Mbuf data is copied.
+*
+*******************************************************************************/
+MV_STATUS mvCesaCopyFromMbuf(MV_U8* pDstBuf, MV_CESA_MBUF* pSrcMbuf,
+ int offset, int size)
+{
+ int frag, fragOffset, bufSize;
+ MV_U8* pBuf;
+
+ if(size == 0)
+ return MV_OK;
+
+ frag = mvCesaMbufOffset(pSrcMbuf, offset, &fragOffset);
+ if(frag == MV_INVALID)
+ {
+ mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+ return MV_OUT_OF_RANGE;
+ }
+
+ bufSize = pSrcMbuf->pFrags[frag].bufSize - fragOffset;
+ pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+ while(MV_TRUE)
+ {
+ if(size <= bufSize)
+ {
+ memcpy(pDstBuf, pBuf, size);
+ return MV_OK;
+ }
+ memcpy(pDstBuf, pBuf, bufSize);
+ size -= bufSize;
+ frag++;
+ pDstBuf += bufSize;
+ if(frag >= pSrcMbuf->numFrags)
+ break;
+
+ bufSize = pSrcMbuf->pFrags[frag].bufSize;
+ pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr;
+ }
+ mvOsPrintf("mvCesaCopyFromMbuf: Mbuf is EMPTY - %d bytes isn't copied\n",
+ size);
+ return MV_EMPTY;
+}
+
+/*******************************************************************************
+* mvCesaCopyToMbuf - Copy data from continuous buffer to the Mbuf structure
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_U8* pSrcBuf - Pointer to continuous buffer, where data is
+* copied from.
+* MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is
+* copied to.
+* int offset - Offset in the Mbuf structure where located first
+* byte of data should be copied.
+* int size - Size of data should be copied
+*
+* RETURN:
+* MV_OK - Success, all data is copied successfully.
+* MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range.
+* No data is copied.
+* MV_FULL - Multi-buffer structure has not enough place to copy
+* all data. Data from the offset to end of Mbuf data
+* is copied.
+*
+*******************************************************************************/
+MV_STATUS mvCesaCopyToMbuf(MV_U8* pSrcBuf, MV_CESA_MBUF* pDstMbuf,
+ int offset, int size)
+{
+ int frag, fragOffset, bufSize;
+ MV_U8* pBuf;
+
+ if(size == 0)
+ return MV_OK;
+
+ frag = mvCesaMbufOffset(pDstMbuf, offset, &fragOffset);
+ if(frag == MV_INVALID)
+ {
+ mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+ return MV_OUT_OF_RANGE;
+ }
+
+ bufSize = pDstMbuf->pFrags[frag].bufSize - fragOffset;
+ pBuf = pDstMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+ while(MV_TRUE)
+ {
+ if(size <= bufSize)
+ {
+ memcpy(pBuf, pSrcBuf, size);
+ return MV_OK;
+ }
+ memcpy(pBuf, pSrcBuf, bufSize);
+ size -= bufSize;
+ frag++;
+ pSrcBuf += bufSize;
+ if(frag >= pDstMbuf->numFrags)
+ break;
+
+ bufSize = pDstMbuf->pFrags[frag].bufSize;
+ pBuf = pDstMbuf->pFrags[frag].bufVirtPtr;
+ }
+ mvOsPrintf("mvCesaCopyToMbuf: Mbuf is FULL - %d bytes isn't copied\n",
+ size);
+ return MV_FULL;
+}
+
+/*******************************************************************************
+* mvCesaMbufCopy - Copy data from one Mbuf structure to the other Mbuf structure
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+*
+* MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is
+* copied to.
+* int dstMbufOffset - Offset in the dstMbuf structure where first byte
+* of data should be copied to.
+* MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is
+* copied from.
+* int srcMbufOffset - Offset in the srcMbuf structure where first byte
+* of data should be copied from.
+* int size - Size of data should be copied
+*
+* RETURN:
+* MV_OK - Success, all data is copied successfully.
+* MV_OUT_OF_RANGE - Failed, srcMbufOffset or dstMbufOffset is out of
+* srcMbuf or dstMbuf structure correspondently.
+* No data is copied.
+* MV_BAD_SIZE - srcMbuf or dstMbuf structure is too small to copy
+* all data. Partial data is copied
+*
+*******************************************************************************/
+MV_STATUS mvCesaMbufCopy(MV_CESA_MBUF* pMbufDst, int dstMbufOffset,
+ MV_CESA_MBUF* pMbufSrc, int srcMbufOffset, int size)
+{
+ int srcFrag, dstFrag, srcSize, dstSize, srcOffset, dstOffset;
+ int copySize;
+ MV_U8 *pSrc, *pDst;
+
+ if(size == 0)
+ return MV_OK;
+
+ srcFrag = mvCesaMbufOffset(pMbufSrc, srcMbufOffset, &srcOffset);
+ if(srcFrag == MV_INVALID)
+ {
+ mvOsPrintf("CESA srcMbuf Error: offset (%d) out of range\n", srcMbufOffset);
+ return MV_OUT_OF_RANGE;
+ }
+ pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr + srcOffset;
+ srcSize = pMbufSrc->pFrags[srcFrag].bufSize - srcOffset;
+
+ dstFrag = mvCesaMbufOffset(pMbufDst, dstMbufOffset, &dstOffset);
+ if(dstFrag == MV_INVALID)
+ {
+ mvOsPrintf("CESA dstMbuf Error: offset (%d) out of range\n", dstMbufOffset);
+ return MV_OUT_OF_RANGE;
+ }
+ pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr + dstOffset;
+ dstSize = pMbufDst->pFrags[dstFrag].bufSize - dstOffset;
+
+ while(size > 0)
+ {
+ copySize = MV_MIN(srcSize, dstSize);
+ if(size <= copySize)
+ {
+ memcpy(pDst, pSrc, size);
+ return MV_OK;
+ }
+ memcpy(pDst, pSrc, copySize);
+ size -= copySize;
+ srcSize -= copySize;
+ dstSize -= copySize;
+
+ if(srcSize == 0)
+ {
+ srcFrag++;
+ if(srcFrag >= pMbufSrc->numFrags)
+ break;
+
+ pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr;
+ srcSize = pMbufSrc->pFrags[srcFrag].bufSize;
+ }
+
+ if(dstSize == 0)
+ {
+ dstFrag++;
+ if(dstFrag >= pMbufDst->numFrags)
+ break;
+
+ pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr;
+ dstSize = pMbufDst->pFrags[dstFrag].bufSize;
+ }
+ }
+ mvOsPrintf("mvCesaMbufCopy: BAD size - %d bytes isn't copied\n",
+ size);
+
+ return MV_BAD_SIZE;
+}
+
+static MV_STATUS mvCesaMbufCacheUnmap(MV_CESA_MBUF* pMbuf, int offset, int size)
+{
+ int frag, fragOffset, bufSize;
+ MV_U8* pBuf;
+
+ if(size == 0)
+ return MV_OK;
+
+ frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
+ if(frag == MV_INVALID)
+ {
+ mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+ return MV_OUT_OF_RANGE;
+ }
+
+ bufSize = pMbuf->pFrags[frag].bufSize - fragOffset;
+ pBuf = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+ while(MV_TRUE)
+ {
+ if(size <= bufSize)
+ {
+ mvOsCacheUnmap(NULL, mvOsIoVirtToPhy(NULL, pBuf), size);
+ return MV_OK;
+ }
+
+ mvOsCacheUnmap(NULL, mvOsIoVirtToPhy(NULL, pBuf), bufSize);
+ size -= bufSize;
+ frag++;
+ if(frag >= pMbuf->numFrags)
+ break;
+
+ bufSize = pMbuf->pFrags[frag].bufSize;
+ pBuf = pMbuf->pFrags[frag].bufVirtPtr;
+ }
+ mvOsPrintf("%s: Mbuf is FULL - %d bytes isn't Unmapped\n",
+ __FUNCTION__, size);
+ return MV_FULL;
+}
+
+
+/*************************************** Local Functions ******************************/
+
+/*******************************************************************************
+* mvCesaFragReqProcess - Process fragmented request
+*
+* DESCRIPTION:
+* This function processes a fragment of fragmented request (First, Middle or Last)
+*
+*
+* INPUT:
+* MV_CESA_REQ* pReq - Pointer to the request in the request queue.
+*
+* RETURN:
+* MV_OK - The fragment is successfully passed to HW for processing.
+* MV_TERMINATE - Means, that HW finished its work on this packet and no more
+* interrupts will be generated for this request.
+* Function mvCesaReadyGet() must be called to complete request
+* processing and get request result.
+*
+*******************************************************************************/
+static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag)
+{
+ int i, copySize, cryptoDataSize, macDataSize, sid;
+ int cryptoIvOffset, digestOffset;
+ MV_U32 config;
+ MV_CESA_COMMAND* pCmd = pReq->pCmd;
+ MV_CESA_SA* pSA;
+ MV_CESA_MBUF* pMbuf;
+ MV_DMA_DESC* pDmaDesc = pReq->dma[frag].pDmaFirst;
+ MV_U8* pSramBuf = cesaSramVirtPtr->buf;
+ int macTotalLen = 0;
+ int fixOffset, cryptoOffset, macOffset;
+
+ cesaStats.fragCount++;
+
+ sid = pReq->pCmd->sessionId;
+
+ pSA = &pCesaSAD[sid];
+
+ cryptoIvOffset = digestOffset = 0;
+ i = macDataSize = 0;
+ cryptoDataSize = 0;
+
+ /* First fragment processing */
+ if(pReq->fragMode == MV_CESA_FRAG_FIRST)
+ {
+ /* pReq->frags monitors processing of fragmented request between fragments */
+ pReq->frags.bufOffset = 0;
+ pReq->frags.cryptoSize = 0;
+ pReq->frags.macSize = 0;
+
+ config = pSA->config | (MV_CESA_FRAG_FIRST << MV_CESA_FRAG_MODE_OFFSET);
+
+ /* fixOffset can be not equal to zero only for FIRST fragment */
+ fixOffset = pReq->fixOffset;
+ /* For FIRST fragment crypto and mac offsets are taken from pCmd */
+ cryptoOffset = pCmd->cryptoOffset;
+ macOffset = pCmd->macOffset;
+
+ copySize = sizeof(cesaSramVirtPtr->buf) - pReq->fixOffset;
+
+ /* Find fragment size: Must meet all requirements for CRYPTO and MAC
+ * cryptoDataSize - size of data will be encrypted/decrypted in this fragment
+ * macDataSize - size of data will be signed/verified in this fragment
+ * copySize - size of data will be copied from srcMbuf to SRAM and
+ * back to dstMbuf for this fragment
+ */
+ mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset,
+ &copySize, &cryptoDataSize, &macDataSize);
+
+ if( (pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET))
+ {
+ /* CryptoIV special processing */
+ if( (pSA->config & MV_CESA_CRYPTO_MODE_MASK) ==
+ (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT) )
+ {
+ /* In CBC mode for encode direction when IV from user */
+ if( (pCmd->ivFromUser) &&
+ ((pSA->config & MV_CESA_DIRECTION_MASK) ==
+ (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) )
+ {
+
+ /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer,
+ * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place
+ * in the buffer to SRAM IVPointer
+ */
+ i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
+ MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
+ }
+
+ /* Special processing when IV is not located in the first fragment */
+ if(pCmd->ivOffset > (copySize - pSA->cryptoIvSize))
+ {
+ /* Prepare dummy place for cryptoIV in SRAM */
+ cryptoIvOffset = cesaSramVirtPtr->tempCryptoIV - mvCesaSramAddrGet();
+
+ /* For Decryption: Copy IV value from pCmd->ivOffset to Special SRAM place */
+ if((pSA->config & MV_CESA_DIRECTION_MASK) ==
+ (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
+ {
+ i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->tempCryptoIV, &pDmaDesc[i],
+ MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
+ }
+ else
+ {
+ /* For Encryption when IV is NOT from User: */
+ /* Copy IV from SRAM to buffer (pCmd->ivOffset) */
+ if(pCmd->ivFromUser == 0)
+ {
+ /* copy IV value from cryptoIV to Buffer (pCmd->ivOffset) */
+ i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
+ MV_TRUE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
+ }
+ }
+ }
+ else
+ {
+ cryptoIvOffset = pCmd->ivOffset;
+ }
+ }
+ }
+
+ if( (pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ /* MAC digest special processing on Decode direction */
+ if((pSA->config & MV_CESA_DIRECTION_MASK) ==
+ (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
+ {
+ /* Save digest from pCmd->digestOffset */
+ mvCesaCopyFromMbuf(pReq->frags.orgDigest,
+ pCmd->pSrc, pCmd->digestOffset, pSA->digestSize);
+
+ /* If pCmd->digestOffset is not located on the first */
+ if(pCmd->digestOffset > (copySize - pSA->digestSize))
+ {
+ MV_U8 digestZero[MV_CESA_MAX_DIGEST_SIZE];
+
+ /* Set zeros to pCmd->digestOffset (DRAM) */
+ memset(digestZero, 0, MV_CESA_MAX_DIGEST_SIZE);
+ mvCesaCopyToMbuf(digestZero, pCmd->pSrc, pCmd->digestOffset, pSA->digestSize);
+
+ /* Prepare dummy place for digest in SRAM */
+ digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
+ }
+ else
+ {
+ digestOffset = pCmd->digestOffset;
+ }
+ }
+ }
+ /* Update SA in SRAM */
+ if(cesaLastSid != sid)
+ {
+ mvCesaSramSaUpdate(sid, &pDmaDesc[i]);
+ i++;
+ }
+
+ pReq->fragMode = MV_CESA_FRAG_MIDDLE;
+ }
+ else
+ {
+ /* Continue fragment */
+ fixOffset = 0;
+ cryptoOffset = 0;
+ macOffset = 0;
+ if( (pCmd->pSrc->mbufSize - pReq->frags.bufOffset) <= sizeof(cesaSramVirtPtr->buf))
+ {
+ /* Last fragment */
+ config = pSA->config | (MV_CESA_FRAG_LAST << MV_CESA_FRAG_MODE_OFFSET);
+ pReq->fragMode = MV_CESA_FRAG_LAST;
+ copySize = pCmd->pSrc->mbufSize - pReq->frags.bufOffset;
+
+ if( (pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ macDataSize = pCmd->macLength - pReq->frags.macSize;
+
+ /* If pCmd->digestOffset is not located on last fragment */
+ if(pCmd->digestOffset < pReq->frags.bufOffset)
+ {
+ /* Prepare dummy place for digest in SRAM */
+ digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
+ }
+ else
+ {
+ digestOffset = pCmd->digestOffset - pReq->frags.bufOffset;
+ }
+ pReq->frags.newDigestOffset = digestOffset;
+ macTotalLen = pCmd->macLength;
+
+ /* HW can't calculate the Digest correctly for fragmented packets
+ * in the following cases:
+ * - MV88F5182 ||
+ * - MV88F5181L when total macLength more that 16 Kbytes ||
+ * - total macLength more that 64 Kbytes
+ */
+ if( (mvCtrlModelGet() == MV_5182_DEV_ID) ||
+ ( (mvCtrlModelGet() == MV_5181_DEV_ID) &&
+ (mvCtrlRevGet() >= MV_5181L_A0_REV) &&
+ (pCmd->macLength >= (1 << 14)) ) )
+ {
+ return MV_TERMINATE;
+ }
+ }
+ if( (pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ cryptoDataSize = pCmd->cryptoLength - pReq->frags.cryptoSize;
+ }
+
+ /* cryptoIvOffset - don't care */
+ }
+ else
+ {
+ /* WA for MV88F5182 SHA1 and MD5 fragmentation mode */
+ if( (mvCtrlModelGet() == MV_5182_DEV_ID) &&
+ (((pSA->config & MV_CESA_MAC_MODE_MASK) ==
+ (MV_CESA_MAC_MD5 << MV_CESA_MAC_MODE_OFFSET)) ||
+ ((pSA->config & MV_CESA_MAC_MODE_MASK) ==
+ (MV_CESA_MAC_SHA1 << MV_CESA_MAC_MODE_OFFSET))) )
+ {
+ pReq->frags.newDigestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
+ pReq->fragMode = MV_CESA_FRAG_LAST;
+
+ return MV_TERMINATE;
+ }
+ /* Middle fragment */
+ config = pSA->config | (MV_CESA_FRAG_MIDDLE << MV_CESA_FRAG_MODE_OFFSET);
+ copySize = sizeof(cesaSramVirtPtr->buf);
+ /* digestOffset and cryptoIvOffset - don't care */
+
+ /* Find fragment size */
+ mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset,
+ &copySize, &cryptoDataSize, &macDataSize);
+ }
+ }
+ /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
+ pMbuf = pCmd->pSrc;
+ i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
+ MV_FALSE, pReq->frags.bufOffset, copySize, pCmd->skipFlush);
+
+ /* Prepare CESA descriptor to copy from DRAM to SRAM by DMA */
+ mvCesaSramDescrBuild(config, frag,
+ cryptoOffset + fixOffset, cryptoIvOffset + fixOffset,
+ cryptoDataSize, macOffset + fixOffset,
+ digestOffset + fixOffset, macDataSize, macTotalLen,
+ pReq, &pDmaDesc[i]);
+ i++;
+
+ /* Add special descriptor Ownership for CPU */
+ pDmaDesc[i].byteCnt = 0;
+ pDmaDesc[i].phySrcAdd = 0;
+ pDmaDesc[i].phyDestAdd = 0;
+ i++;
+
+ /********* Prepare DMA descriptors to copy from SRAM to pDst *********/
+ pMbuf = pCmd->pDst;
+ i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
+ MV_TRUE, pReq->frags.bufOffset, copySize, pCmd->skipFlush);
+
+ /* Next field of Last DMA descriptor must be NULL */
+ pDmaDesc[i-1].phyNextDescPtr = 0;
+ pReq->dma[frag].pDmaLast = &pDmaDesc[i-1];
+ mvOsCacheFlush(NULL, pReq->dma[frag].pDmaFirst,
+ i*sizeof(MV_DMA_DESC));
+
+ /*mvCesaDebugDescriptor(&cesaSramVirtPtr->desc[frag]);*/
+
+ pReq->frags.bufOffset += copySize;
+ pReq->frags.cryptoSize += cryptoDataSize;
+ pReq->frags.macSize += macDataSize;
+
+ return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvCesaReqProcess - Process regular (Non-fragmented) request
+*
+* DESCRIPTION:
+* This function processes the whole (not fragmented) request
+*
+* INPUT:
+* MV_CESA_REQ* pReq - Pointer to the request in the request queue.
+*
+* RETURN:
+* MV_OK - The request is successfully passed to HW for processing.
+* Other - Failure. The request will not be processed
+*
+*******************************************************************************/
+static MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq)
+{
+ MV_CESA_MBUF *pMbuf;
+ MV_DMA_DESC *pDmaDesc;
+ MV_U8 *pSramBuf;
+ int sid, i, fixOffset;
+ MV_CESA_SA *pSA;
+ MV_CESA_COMMAND *pCmd = pReq->pCmd;
+
+ cesaStats.procCount++;
+
+ sid = pCmd->sessionId;
+ pSA = &pCesaSAD[sid];
+ pDmaDesc = pReq->dma[0].pDmaFirst;
+ pSramBuf = cesaSramVirtPtr->buf;
+ fixOffset = pReq->fixOffset;
+
+/*
+ mvOsPrintf("mvCesaReqProcess: sid=%d, pSA=%p, pDmaDesc=%p, pSramBuf=%p\n",
+ sid, pSA, pDmaDesc, pSramBuf);
+*/
+ i = 0;
+
+ /* Crypto IV Special processing in CBC mode for Encryption direction */
+ if( ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) &&
+ ((pSA->config & MV_CESA_CRYPTO_MODE_MASK) == (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT)) &&
+ ((pSA->config & MV_CESA_DIRECTION_MASK) == (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) &&
+ (pCmd->ivFromUser) )
+ {
+ /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer,
+ * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place
+ * in the buffer to SRAM IVPointer
+ */
+ i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
+ MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
+ }
+
+ /* Update SA in SRAM */
+ if(cesaLastSid != sid)
+ {
+ mvCesaSramSaUpdate(sid, &pDmaDesc[i]);
+ i++;
+ }
+
+ /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
+ pMbuf = pCmd->pSrc;
+ i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
+ MV_FALSE, 0, pMbuf->mbufSize, pCmd->skipFlush);
+
+ /* Prepare Security Accelerator descriptor to SRAM words 0 - 7 */
+ mvCesaSramDescrBuild(pSA->config, 0, pCmd->cryptoOffset + fixOffset,
+ pCmd->ivOffset + fixOffset, pCmd->cryptoLength,
+ pCmd->macOffset + fixOffset, pCmd->digestOffset + fixOffset,
+ pCmd->macLength, pCmd->macLength, pReq, &pDmaDesc[i]);
+ i++;
+
+ /* Add special descriptor Ownership for CPU */
+ pDmaDesc[i].byteCnt = 0;
+ pDmaDesc[i].phySrcAdd = 0;
+ pDmaDesc[i].phyDestAdd = 0;
+ i++;
+
+ /********* Prepare DMA descriptors to copy from SRAM to pDst *********/
+ pMbuf = pCmd->pDst;
+ i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
+ MV_TRUE, 0, pMbuf->mbufSize, pCmd->skipFlush);
+
+ /* Next field of Last DMA descriptor must be NULL */
+ pDmaDesc[i-1].phyNextDescPtr = 0;
+ pReq->dma[0].pDmaLast = &pDmaDesc[i-1];
+ mvOsCacheFlush(NULL, pReq->dma[0].pDmaFirst, i*sizeof(MV_DMA_DESC));
+
+ return MV_OK;
+}
+
+
+/*******************************************************************************
+* mvCesaSramDescrBuild - Set CESA descriptor in SRAM
+*
+* DESCRIPTION:
+* This function builds CESA descriptor in SRAM from all Command parameters
+*
+*
+* INPUT:
+* int chan - CESA channel uses the descriptor
+* MV_U32 config - 32 bits of WORD_0 in CESA descriptor structure
+* int cryptoOffset - Offset from the beginning of SRAM buffer where
+* data for encryption/decription is started.
+* int ivOffset - Offset of crypto IV from the SRAM base. Valid only
+* for first fragment.
+* int cryptoLength - Size (in bytes) of data for encryption/descryption
+* operation on this fragment.
+* int macOffset - Offset from the beginning of SRAM buffer where
+* data for Authentication is started
+* int digestOffset - Offset from the beginning of SRAM buffer where
+* digest is located. Valid for first and last fragments.
+* int macLength - Size (in bytes) of data for Authentication
+* operation on this fragment.
+* int macTotalLen - Toatl size (in bytes) of data for Authentication
+* operation on the whole request (packet). Valid for
+* last fragment only.
+*
+* RETURN: None
+*
+*******************************************************************************/
+static void mvCesaSramDescrBuild(MV_U32 config, int frag,
+ int cryptoOffset, int ivOffset, int cryptoLength,
+ int macOffset, int digestOffset, int macLength,
+ int macTotalLen, MV_CESA_REQ* pReq, MV_DMA_DESC* pDmaDesc)
+{
+ MV_CESA_DESC* pCesaDesc = &pReq->pCesaDesc[frag];
+ MV_CESA_DESC* pSramDesc = pSramDesc = &cesaSramVirtPtr->desc;
+ MV_U16 sramBufOffset = (MV_U16)((MV_U8*)cesaSramVirtPtr->buf - mvCesaSramAddrGet());
+
+ pCesaDesc->config = MV_32BIT_LE(config);
+
+ if( (config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ /* word 1 */
+ pCesaDesc->cryptoSrcOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset);
+ pCesaDesc->cryptoDstOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset);
+ /* word 2 */
+ pCesaDesc->cryptoDataLen = MV_16BIT_LE(cryptoLength);
+ /* word 3 */
+ pCesaDesc->cryptoKeyOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.cryptoKey -
+ mvCesaSramAddrGet()));
+ /* word 4 */
+ pCesaDesc->cryptoIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->cryptoIV -
+ mvCesaSramAddrGet()));
+ pCesaDesc->cryptoIvBufOffset = MV_16BIT_LE(sramBufOffset + ivOffset);
+ }
+
+ if( (config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ /* word 5 */
+ pCesaDesc->macSrcOffset = MV_16BIT_LE(sramBufOffset + macOffset);
+ pCesaDesc->macTotalLen = MV_16BIT_LE(macTotalLen);
+
+ /* word 6 */
+ pCesaDesc->macDigestOffset = MV_16BIT_LE(sramBufOffset + digestOffset);
+ pCesaDesc->macDataLen = MV_16BIT_LE(macLength);
+
+ /* word 7 */
+ pCesaDesc->macInnerIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macInnerIV -
+ mvCesaSramAddrGet()));
+ pCesaDesc->macOuterIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macOuterIV -
+ mvCesaSramAddrGet()));
+ }
+ /* Prepare DMA descriptor to CESA descriptor from DRAM to SRAM */
+ pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&pReq->cesaDescBuf, pCesaDesc));
+ pDmaDesc->phyDestAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)pSramDesc));
+ pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_DESC) | BIT31);
+
+ /* flush Source buffer */
+ mvOsCacheFlush(NULL, pCesaDesc, sizeof(MV_CESA_DESC));
+}
+
+/*******************************************************************************
+* mvCesaSramSaUpdate - Move required SA information to SRAM if needed.
+*
+* DESCRIPTION:
+* Copy to SRAM values of the required SA.
+*
+*
+* INPUT:
+* short sid - Session ID needs SRAM Cache update
+* MV_DMA_DESC *pDmaDesc - Pointer to DMA descriptor used to
+* copy SA values from DRAM to SRAM.
+*
+* RETURN:
+* MV_OK - Cache entry for this SA copied to SRAM.
+* MV_NO_CHANGE - Cache entry for this SA already exist in SRAM
+*
+*******************************************************************************/
+static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc)
+{
+ MV_CESA_SA *pSA = &pCesaSAD[sid];
+
+ /* Prepare DMA descriptor to Copy CACHE_SA from SA database in DRAM to SRAM */
+ pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_SRAM_SA) | BIT31);
+ pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&cesaSramSaBuf, pSA->pSramSA));
+ pDmaDesc->phyDestAdd =
+ MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)&cesaSramVirtPtr->sramSA));
+
+ /* Source buffer is already flushed during OpenSession*/
+ /*mvOsCacheFlush(NULL, &pSA->sramSA, sizeof(MV_CESA_SRAM_SA));*/
+}
+
+/*******************************************************************************
+* mvCesaDmaCopyPrepare - prepare DMA descriptor list to copy data presented by
+* Mbuf structure from DRAM to SRAM
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_MBUF* pMbuf - pointer to Mbuf structure contains request
+* data in DRAM
+* MV_U8* pSramBuf - pointer to buffer in SRAM where data should
+* be copied to.
+* MV_DMA_DESC* pDmaDesc - pointer to first DMA descriptor for this copy.
+* The function set number of DMA descriptors needed
+* to copy the copySize bytes from Mbuf.
+* MV_BOOL isToMbuf - Copy direction.
+* MV_TRUE means copy from SRAM buffer to Mbuf in DRAM.
+* MV_FALSE means copy from Mbuf in DRAM to SRAM buffer.
+* int offset - Offset in the Mbuf structure that copy should be
+* started from.
+* int copySize - Size of data should be copied.
+*
+* RETURN:
+* int - number of DMA descriptors used for the copy.
+*
+*******************************************************************************/
+#ifndef MV_NETBSD
+static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
+ MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
+ int offset, int copySize, MV_BOOL skipFlush)
+{
+ int bufOffset, bufSize, size, frag, i;
+ MV_U8* pBuf;
+
+ i = 0;
+
+ /* Calculate start place for copy: fragment number and offset in the fragment */
+ frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset);
+ bufSize = pMbuf->pFrags[frag].bufSize - bufOffset;
+ pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset;
+
+ /* Size accumulate total copy size */
+ size = 0;
+
+ /* Create DMA lists to copy mBuf from pSrc to SRAM */
+ while(size < copySize)
+ {
+ /* Find copy size for each DMA descriptor */
+ bufSize = MV_MIN(bufSize, (copySize - size));
+ pDmaDesc[i].byteCnt = MV_32BIT_LE(bufSize | BIT31);
+ if(isToMbuf)
+ {
+ pDmaDesc[i].phyDestAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
+ pDmaDesc[i].phySrcAdd =
+ MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size)));
+ /* invalidate the buffer */
+ if(skipFlush == MV_FALSE)
+ mvOsCacheInvalidate(NULL, pBuf, bufSize);
+ }
+ else
+ {
+ pDmaDesc[i].phySrcAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
+ pDmaDesc[i].phyDestAdd =
+ MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size)));
+ /* flush the buffer */
+ if(skipFlush == MV_FALSE)
+ mvOsCacheFlush(NULL, pBuf, bufSize);
+ }
+
+ /* Count number of used DMA descriptors */
+ i++;
+ size += bufSize;
+
+ /* go to next fragment in the Mbuf */
+ frag++;
+ pBuf = pMbuf->pFrags[frag].bufVirtPtr;
+ bufSize = pMbuf->pFrags[frag].bufSize;
+ }
+ return i;
+}
+#else /* MV_NETBSD */
+static int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
+ MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
+ int offset, int copySize, MV_BOOL skipFlush)
+{
+ int bufOffset, bufSize, thisSize, size, frag, i;
+ MV_ULONG bufPhys, sramPhys;
+ MV_U8* pBuf;
+
+ /*
+ * Calculate start place for copy: fragment number and offset in
+ * the fragment
+ */
+ frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset);
+
+ /*
+ * Get SRAM physical address only once. We can update it in-place
+ * as we build the descriptor chain.
+ */
+ sramPhys = mvCesaSramVirtToPhys(NULL, pSramBuf);
+
+ /*
+ * 'size' accumulates total copy size, 'i' counts desccriptors.
+ */
+ size = i = 0;
+
+ /* Create DMA lists to copy mBuf from pSrc to SRAM */
+ while (size < copySize) {
+ /*
+ * Calculate # of bytes to copy from the current fragment,
+ * and the pointer to the start of data
+ */
+ bufSize = pMbuf->pFrags[frag].bufSize - bufOffset;
+ pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset;
+ bufOffset = 0; /* First frag may be non-zero */
+ frag++;
+
+ /*
+ * As long as there is data in the current fragment...
+ */
+ while (bufSize > 0) {
+ /*
+ * Ensure we don't cross an MMU page boundary.
+ * XXX: This is NetBSD-specific, but it is a
+ * quick and dirty way to fix the problem.
+ * A true HAL would rely on the OS-specific
+ * driver to do this...
+ */
+ thisSize = PAGE_SIZE -
+ (((MV_ULONG)pBuf) & (PAGE_SIZE - 1));
+ thisSize = MV_MIN(bufSize, thisSize);
+ /*
+ * Make sure we don't copy more than requested
+ */
+ if (thisSize > (copySize - size)) {
+ thisSize = copySize - size;
+ bufSize = 0;
+ }
+
+ /*
+ * Physicall address of this fragment
+ */
+ bufPhys = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
+
+ /*
+ * Set up the descriptor
+ */
+ pDmaDesc[i].byteCnt = MV_32BIT_LE(thisSize | BIT31);
+ if(isToMbuf) {
+ pDmaDesc[i].phyDestAdd = bufPhys;
+ pDmaDesc[i].phySrcAdd = MV_32BIT_LE(sramPhys);
+ /* invalidate the buffer */
+ if(skipFlush == MV_FALSE)
+ mvOsCacheInvalidate(NULL, pBuf, thisSize);
+ } else {
+ pDmaDesc[i].phySrcAdd = bufPhys;
+ pDmaDesc[i].phyDestAdd = MV_32BIT_LE(sramPhys);
+ /* flush the buffer */
+ if(skipFlush == MV_FALSE)
+ mvOsCacheFlush(NULL, pBuf, thisSize);
+ }
+
+ pDmaDesc[i].phyNextDescPtr =
+ MV_32BIT_LE(mvOsIoVirtToPhy(NULL,(&pDmaDesc[i+1])));
+
+ /* flush the DMA desc */
+ mvOsCacheFlush(NULL, &pDmaDesc[i], sizeof(MV_DMA_DESC));
+
+ /* Update state */
+ bufSize -= thisSize;
+ sramPhys += thisSize;
+ pBuf += thisSize;
+ size += thisSize;
+ i++;
+ }
+ }
+
+ return i;
+}
+#endif /* MV_NETBSD */
+/*******************************************************************************
+* mvCesaHmacIvGet - Calculate Inner and Outter values from HMAC key
+*
+* DESCRIPTION:
+* This function calculate Inner and Outer values used for HMAC algorithm.
+* This operation allows improve performance fro the whole HMAC processing.
+*
+* INPUT:
+* MV_CESA_MAC_MODE macMode - Authentication mode: HMAC_MD5 or HMAC_SHA1.
+* unsigned char key[] - Pointer to HMAC key.
+* int keyLength - Size of HMAC key (maximum 64 bytes)
+*
+* OUTPUT:
+* unsigned char innerIV[] - HASH(key^inner)
+* unsigned char outerIV[] - HASH(key^outter)
+*
+* RETURN: None
+*
+*******************************************************************************/
+static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
+ unsigned char innerIV[], unsigned char outerIV[])
+{
+ unsigned char inner[MV_CESA_MAX_MAC_KEY_LENGTH];
+ unsigned char outer[MV_CESA_MAX_MAC_KEY_LENGTH];
+ int i, digestSize = 0;
+#if defined(MV_CPU_LE) || defined(MV_PPC)
+ MV_U32 swapped32, val32, *pVal32;
+#endif
+ for(i=0; i<keyLength; i++)
+ {
+ inner[i] = 0x36 ^ key[i];
+ outer[i] = 0x5c ^ key[i];
+ }
+
+ for(i=keyLength; i<MV_CESA_MAX_MAC_KEY_LENGTH; i++)
+ {
+ inner[i] = 0x36;
+ outer[i] = 0x5c;
+ }
+ if(macMode == MV_CESA_MAC_HMAC_MD5)
+ {
+ MV_MD5_CONTEXT ctx;
+
+ mvMD5Init(&ctx);
+ mvMD5Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
+
+ memcpy(innerIV, ctx.buf, MV_CESA_MD5_DIGEST_SIZE);
+ memset(&ctx, 0, sizeof(ctx));
+
+ mvMD5Init(&ctx);
+ mvMD5Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
+ memcpy(outerIV, ctx.buf, MV_CESA_MD5_DIGEST_SIZE);
+ memset(&ctx, 0, sizeof(ctx));
+ digestSize = MV_CESA_MD5_DIGEST_SIZE;
+ }
+ else if(macMode == MV_CESA_MAC_HMAC_SHA1)
+ {
+ MV_SHA1_CTX ctx;
+
+ mvSHA1Init(&ctx);
+ mvSHA1Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
+ memcpy(innerIV, ctx.state, MV_CESA_SHA1_DIGEST_SIZE);
+ memset(&ctx, 0, sizeof(ctx));
+
+ mvSHA1Init(&ctx);
+ mvSHA1Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
+ memcpy(outerIV, ctx.state, MV_CESA_SHA1_DIGEST_SIZE);
+ memset(&ctx, 0, sizeof(ctx));
+ digestSize = MV_CESA_SHA1_DIGEST_SIZE;
+ }
+ else
+ {
+ mvOsPrintf("hmacGetIV: Unexpected macMode %d\n", macMode);
+ }
+#if defined(MV_CPU_LE) || defined(MV_PPC)
+ /* 32 bits Swap of Inner and Outer values */
+ pVal32 = (MV_U32*)innerIV;
+ for(i=0; i<digestSize/4; i++)
+ {
+ val32 = *pVal32;
+ swapped32 = MV_BYTE_SWAP_32BIT(val32);
+ *pVal32 = swapped32;
+ pVal32++;
+ }
+ pVal32 = (MV_U32*)outerIV;
+ for(i=0; i<digestSize/4; i++)
+ {
+ val32 = *pVal32;
+ swapped32 = MV_BYTE_SWAP_32BIT(val32);
+ *pVal32 = swapped32;
+ pVal32++;
+ }
+#endif /* defined(MV_CPU_LE) || defined(MV_PPC) */
+}
+
+
+/*******************************************************************************
+* mvCesaFragSha1Complete - Complete SHA1 authentication started by HW using SW
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_MBUF* pMbuf - Pointer to Mbuf structure where data
+* for SHA1 is placed.
+* int offset - Offset in the Mbuf structure where
+* unprocessed data for SHA1 is started.
+* MV_U8* pOuterIV - Pointer to OUTER for this session.
+* If pOuterIV==NULL - MAC mode is HASH_SHA1
+* If pOuterIV!=NULL - MAC mode is HMAC_SHA1
+* int macLeftSize - Size of unprocessed data for SHA1.
+* int macTotalSize - Total size of data for SHA1 in the
+* request (processed + unprocessed)
+*
+* OUTPUT:
+* MV_U8* pDigest - Pointer to place where calculated Digest will
+* be stored.
+*
+* RETURN: None
+*
+*******************************************************************************/
+static void mvCesaFragSha1Complete(MV_CESA_MBUF* pMbuf, int offset,
+ MV_U8* pOuterIV, int macLeftSize,
+ int macTotalSize, MV_U8* pDigest)
+{
+ MV_SHA1_CTX ctx;
+ MV_U8 *pData;
+ int i, frag, fragOffset, size;
+
+ /* Read temporary Digest from HW */
+ for(i=0; i<MV_CESA_SHA1_DIGEST_SIZE/4; i++)
+ {
+ ctx.state[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(i));
+ }
+ /* Initialize MV_SHA1_CTX structure */
+ memset(ctx.buffer, 0, 64);
+ /* Set count[0] in bits. 32 bits is enough for 512 MBytes */
+ /* so count[1] is always 0 */
+ ctx.count[0] = ((macTotalSize - macLeftSize) * 8);
+ ctx.count[1] = 0;
+
+ /* If HMAC - add size of Inner block (64 bytes) ro count[0] */
+ if(pOuterIV != NULL)
+ ctx.count[0] += (64 * 8);
+
+ /* Get place of unprocessed data in the Mbuf structure */
+ frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
+ if(frag == MV_INVALID)
+ {
+ mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+ return;
+ }
+
+ pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+ size = pMbuf->pFrags[frag].bufSize - fragOffset;
+
+ /* Complete Inner part */
+ while(macLeftSize > 0)
+ {
+ if(macLeftSize <= size)
+ {
+ mvSHA1Update(&ctx, pData, macLeftSize);
+ break;
+ }
+ mvSHA1Update(&ctx, pData, size);
+ macLeftSize -= size;
+ frag++;
+ pData = pMbuf->pFrags[frag].bufVirtPtr;
+ size = pMbuf->pFrags[frag].bufSize;
+ }
+ mvSHA1Final(pDigest, &ctx);
+/*
+ mvOsPrintf("mvCesaFragSha1Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
+ pOuterIV, macLeftSize, macTotalSize);
+ mvDebugMemDump(pDigest, MV_CESA_SHA1_DIGEST_SIZE, 1);
+*/
+
+ if(pOuterIV != NULL)
+ {
+ /* If HMAC - Complete Outer part */
+ for(i=0; i<MV_CESA_SHA1_DIGEST_SIZE/4; i++)
+ {
+#if defined(MV_CPU_LE) || defined(MV_ARM)
+ ctx.state[i] = MV_BYTE_SWAP_32BIT(((MV_U32*)pOuterIV)[i]);
+#else
+ ctx.state[i] = ((MV_U32*)pOuterIV)[i];
+#endif
+ }
+ memset(ctx.buffer, 0, 64);
+
+ ctx.count[0] = 64*8;
+ ctx.count[1] = 0;
+ mvSHA1Update(&ctx, pDigest, MV_CESA_SHA1_DIGEST_SIZE);
+ mvSHA1Final(pDigest, &ctx);
+ }
+}
+
+/*******************************************************************************
+* mvCesaFragMd5Complete - Complete MD5 authentication started by HW using SW
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_MBUF* pMbuf - Pointer to Mbuf structure where data
+* for SHA1 is placed.
+* int offset - Offset in the Mbuf structure where
+* unprocessed data for MD5 is started.
+* MV_U8* pOuterIV - Pointer to OUTER for this session.
+* If pOuterIV==NULL - MAC mode is HASH_MD5
+* If pOuterIV!=NULL - MAC mode is HMAC_MD5
+* int macLeftSize - Size of unprocessed data for MD5.
+* int macTotalSize - Total size of data for MD5 in the
+* request (processed + unprocessed)
+*
+* OUTPUT:
+* MV_U8* pDigest - Pointer to place where calculated Digest will
+* be stored.
+*
+* RETURN: None
+*
+*******************************************************************************/
+static void mvCesaFragMd5Complete(MV_CESA_MBUF* pMbuf, int offset,
+ MV_U8* pOuterIV, int macLeftSize,
+ int macTotalSize, MV_U8* pDigest)
+{
+ MV_MD5_CONTEXT ctx;
+ MV_U8 *pData;
+ int i, frag, fragOffset, size;
+
+ /* Read temporary Digest from HW */
+ for(i=0; i<MV_CESA_MD5_DIGEST_SIZE/4; i++)
+ {
+ ctx.buf[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(i));
+ }
+ memset(ctx.in, 0, 64);
+
+ /* Set count[0] in bits. 32 bits is enough for 512 MBytes */
+ /* so count[1] is always 0 */
+ ctx.bits[0] = ((macTotalSize - macLeftSize) * 8);
+ ctx.bits[1] = 0;
+
+ /* If HMAC - add size of Inner block (64 bytes) ro count[0] */
+ if(pOuterIV != NULL)
+ ctx.bits[0] += (64 * 8);
+
+ frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
+ if(frag == MV_INVALID)
+ {
+ mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
+ return;
+ }
+
+ pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
+ size = pMbuf->pFrags[frag].bufSize - fragOffset;
+
+ /* Complete Inner part */
+ while(macLeftSize > 0)
+ {
+ if(macLeftSize <= size)
+ {
+ mvMD5Update(&ctx, pData, macLeftSize);
+ break;
+ }
+ mvMD5Update(&ctx, pData, size);
+ macLeftSize -= size;
+ frag++;
+ pData = pMbuf->pFrags[frag].bufVirtPtr;
+ size = pMbuf->pFrags[frag].bufSize;
+ }
+ mvMD5Final(pDigest, &ctx);
+
+/*
+ mvOsPrintf("mvCesaFragMd5Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
+ pOuterIV, macLeftSize, macTotalSize);
+ mvDebugMemDump(pDigest, MV_CESA_MD5_DIGEST_SIZE, 1);
+*/
+ if(pOuterIV != NULL)
+ {
+ /* Complete Outer part */
+ for(i=0; i<MV_CESA_MD5_DIGEST_SIZE/4; i++)
+ {
+#if defined(MV_CPU_LE) || defined(MV_ARM)
+ ctx.buf[i] = MV_BYTE_SWAP_32BIT(((MV_U32*)pOuterIV)[i]);
+#else
+ ctx.buf[i] = ((MV_U32*)pOuterIV)[i];
+#endif
+ }
+ memset(ctx.in, 0, 64);
+
+ ctx.bits[0] = 64*8;
+ ctx.bits[1] = 0;
+ mvMD5Update(&ctx, pDigest, MV_CESA_MD5_DIGEST_SIZE);
+ mvMD5Final(pDigest, &ctx);
+ }
+}
+
+/*******************************************************************************
+* mvCesaFragAuthComplete -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_REQ* pReq,
+* MV_CESA_SA* pSA,
+* int macDataSize
+*
+* RETURN:
+* MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaFragAuthComplete(MV_CESA_REQ* pReq, MV_CESA_SA* pSA,
+ int macDataSize)
+{
+ MV_CESA_COMMAND* pCmd = pReq->pCmd;
+ MV_U8* pDigest;
+ MV_CESA_MAC_MODE macMode;
+ MV_U8* pOuterIV = NULL;
+
+ /* Copy data from Source fragment to Destination */
+ if(pCmd->pSrc != pCmd->pDst)
+ {
+ mvCesaMbufCopy(pCmd->pDst, pReq->frags.bufOffset,
+ pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
+ }
+
+/*
+ mvCesaCopyFromMbuf(cesaSramVirtPtr->buf[0], pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
+ mvCesaCopyToMbuf(cesaSramVirtPtr->buf[0], pCmd->pDst, pReq->frags.bufOffset, macDataSize);
+*/
+ pDigest = (mvCesaSramAddrGet() + pReq->frags.newDigestOffset);
+
+ macMode = (pSA->config & MV_CESA_MAC_MODE_MASK) >> MV_CESA_MAC_MODE_OFFSET;
+/*
+ mvOsPrintf("macDataSize=%d, macLength=%d, digestOffset=%d, macMode=%d\n",
+ macDataSize, pCmd->macLength, pCmd->digestOffset, macMode);
+*/
+ switch(macMode)
+ {
+ case MV_CESA_MAC_HMAC_MD5:
+ pOuterIV = pSA->pSramSA->macOuterIV;
+
+ case MV_CESA_MAC_MD5:
+ mvCesaFragMd5Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
+ macDataSize, pCmd->macLength, pDigest);
+ break;
+
+ case MV_CESA_MAC_HMAC_SHA1:
+ pOuterIV = pSA->pSramSA->macOuterIV;
+
+ case MV_CESA_MAC_SHA1:
+ mvCesaFragSha1Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
+ macDataSize, pCmd->macLength, pDigest);
+ break;
+
+ default:
+ mvOsPrintf("mvCesaFragAuthComplete: Unexpected macMode %d\n", macMode);
+ return MV_BAD_PARAM;
+ }
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaCtrModeInit -
+*
+* DESCRIPTION:
+*
+*
+* INPUT: NONE
+*
+*
+* RETURN:
+* MV_CESA_COMMAND*
+*
+*******************************************************************************/
+static MV_CESA_COMMAND* mvCesaCtrModeInit(void)
+{
+ MV_CESA_MBUF *pMbuf;
+ MV_U8 *pBuf;
+ MV_CESA_COMMAND *pCmd;
+
+ pBuf = mvOsMalloc(sizeof(MV_CESA_COMMAND) +
+ sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) + 100);
+ if(pBuf == NULL)
+ {
+ mvOsPrintf("mvCesaSessionOpen: Can't allocate %u bytes for CTR Mode\n",
+ sizeof(MV_CESA_COMMAND) + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) );
+ return NULL;
+ }
+ pCmd = (MV_CESA_COMMAND*)pBuf;
+ pBuf += sizeof(MV_CESA_COMMAND);
+
+ pMbuf = (MV_CESA_MBUF*)pBuf;
+ pBuf += sizeof(MV_CESA_MBUF);
+
+ pMbuf->pFrags = (MV_BUF_INFO*)pBuf;
+
+ pMbuf->numFrags = 1;
+ pCmd->pSrc = pMbuf;
+ pCmd->pDst = pMbuf;
+/*
+ mvOsPrintf("CtrModeInit: pCmd=%p, pSrc=%p, pDst=%p, pFrags=%p\n",
+ pCmd, pCmd->pSrc, pCmd->pDst,
+ pMbuf->pFrags);
+*/
+ return pCmd;
+}
+
+/*******************************************************************************
+* mvCesaCtrModePrepare -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd
+*
+* RETURN:
+* MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd)
+{
+ MV_CESA_MBUF *pMbuf;
+ MV_U8 *pBuf, *pIV;
+ MV_U32 counter, *pCounter;
+ int cryptoSize = MV_ALIGN_UP(pCmd->cryptoLength, MV_CESA_AES_BLOCK_SIZE);
+/*
+ mvOsPrintf("CtrModePrepare: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n",
+ pCmd, pCmd->pSrc, pCmd->pDst,
+ pCtrModeCmd, pCtrModeCmd->pSrc, pCtrModeCmd->pDst);
+*/
+ pMbuf = pCtrModeCmd->pSrc;
+
+ /* Allocate buffer for Key stream */
+ pBuf = mvOsIoCachedMalloc(cesaOsHandle,cryptoSize,
+ &pMbuf->pFrags[0].bufPhysAddr,
+ &pMbuf->pFrags[0].memHandle);
+ if(pBuf == NULL)
+ {
+ mvOsPrintf("mvCesaCtrModePrepare: Can't allocate %d bytes\n", cryptoSize);
+ return MV_OUT_OF_CPU_MEM;
+ }
+ memset(pBuf, 0, cryptoSize);
+ mvOsCacheFlush(NULL, pBuf, cryptoSize);
+
+ pMbuf->pFrags[0].bufVirtPtr = pBuf;
+ pMbuf->mbufSize = cryptoSize;
+ pMbuf->pFrags[0].bufSize = cryptoSize;
+
+ pCtrModeCmd->pReqPrv = pCmd->pReqPrv;
+ pCtrModeCmd->sessionId = pCmd->sessionId;
+
+ /* ivFromUser and ivOffset are don't care */
+ pCtrModeCmd->cryptoOffset = 0;
+ pCtrModeCmd->cryptoLength = cryptoSize;
+
+ /* digestOffset, macOffset and macLength are don't care */
+
+ mvCesaCopyFromMbuf(pBuf, pCmd->pSrc, pCmd->ivOffset, MV_CESA_AES_BLOCK_SIZE);
+ pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter)));
+ counter = *pCounter;
+ counter = MV_32BIT_BE(counter);
+ pIV = pBuf;
+ cryptoSize -= MV_CESA_AES_BLOCK_SIZE;
+
+ /* fill key stream */
+ while(cryptoSize > 0)
+ {
+ pBuf += MV_CESA_AES_BLOCK_SIZE;
+ memcpy(pBuf, pIV, MV_CESA_AES_BLOCK_SIZE - sizeof(counter));
+ pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter)));
+ counter++;
+ *pCounter = MV_32BIT_BE(counter);
+ cryptoSize -= MV_CESA_AES_BLOCK_SIZE;
+ }
+
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaCtrModeComplete -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd
+*
+* RETURN:
+* MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd)
+{
+ int srcFrag, dstFrag, srcOffset, dstOffset, keyOffset, srcSize, dstSize;
+ int cryptoSize = pCmd->cryptoLength;
+ MV_U8 *pSrc, *pDst, *pKey;
+ MV_STATUS status = MV_OK;
+/*
+ mvOsPrintf("CtrModeComplete: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n",
+ pCmd, pCmd->pSrc, pCmd->pDst,
+ pOrgCmd, pOrgCmd->pSrc, pOrgCmd->pDst);
+*/
+ /* XOR source data with key stream to destination data */
+ pKey = pCmd->pDst->pFrags[0].bufVirtPtr;
+ keyOffset = 0;
+
+ if( (pOrgCmd->pSrc != pOrgCmd->pDst) &&
+ (pOrgCmd->cryptoOffset > 0) )
+ {
+ /* Copy Prefix from source buffer to destination buffer */
+
+ status = mvCesaMbufCopy(pOrgCmd->pDst, 0,
+ pOrgCmd->pSrc, 0, pOrgCmd->cryptoOffset);
+/*
+ status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc,
+ 0, pOrgCmd->cryptoOffset);
+ status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst,
+ 0, pOrgCmd->cryptoOffset);
+*/
+ }
+
+ srcFrag = mvCesaMbufOffset(pOrgCmd->pSrc, pOrgCmd->cryptoOffset, &srcOffset);
+ pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr;
+ srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize;
+
+ dstFrag = mvCesaMbufOffset(pOrgCmd->pDst, pOrgCmd->cryptoOffset, &dstOffset);
+ pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr;
+ dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize;
+
+ while(cryptoSize > 0)
+ {
+ pDst[dstOffset] = (pSrc[srcOffset] ^ pKey[keyOffset]);
+
+ cryptoSize--;
+ dstOffset++;
+ srcOffset++;
+ keyOffset++;
+
+ if(srcOffset >= srcSize)
+ {
+ srcFrag++;
+ srcOffset = 0;
+ pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr;
+ srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize;
+ }
+
+ if(dstOffset >= dstSize)
+ {
+ dstFrag++;
+ dstOffset = 0;
+ pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr;
+ dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize;
+ }
+ }
+
+ if(pOrgCmd->pSrc != pOrgCmd->pDst)
+ {
+ /* Copy Suffix from source buffer to destination buffer */
+ srcOffset = pOrgCmd->cryptoOffset + pOrgCmd->cryptoLength;
+
+ if( (pOrgCmd->pDst->mbufSize - srcOffset) > 0)
+ {
+ status = mvCesaMbufCopy(pOrgCmd->pDst, srcOffset,
+ pOrgCmd->pSrc, srcOffset,
+ pOrgCmd->pDst->mbufSize - srcOffset);
+ }
+
+/*
+ status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc,
+ srcOffset, pOrgCmd->pSrc->mbufSize - srcOffset);
+ status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst,
+ srcOffset, pOrgCmd->pDst->mbufSize - srcOffset);
+*/
+ }
+
+ /* Free buffer used for Key stream */
+ mvOsIoCachedFree(cesaOsHandle,pCmd->pDst->pFrags[0].bufSize,
+ pCmd->pDst->pFrags[0].bufPhysAddr,
+ pCmd->pDst->pFrags[0].bufVirtPtr,
+ pCmd->pDst->pFrags[0].memHandle);
+
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaCtrModeFinish -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_COMMAND* pCmd
+*
+* RETURN:
+* MV_STATUS
+*
+*******************************************************************************/
+static void mvCesaCtrModeFinish(MV_CESA_COMMAND* pCmd)
+{
+ mvOsFree(pCmd);
+}
+
+/*******************************************************************************
+* mvCesaParamCheck -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset
+*
+* RETURN:
+* MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd,
+ MV_U8* pFixOffset)
+{
+ MV_U8 fixOffset = 0xFF;
+
+ /* Check AUTH operation parameters */
+ if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) )
+ {
+ /* MAC offset should be at least 4 byte aligned */
+ if( MV_IS_NOT_ALIGN(pCmd->macOffset, 4) )
+ {
+ mvOsPrintf("mvCesaAction: macOffset %d must be 4 byte aligned\n",
+ pCmd->macOffset);
+ return MV_BAD_PARAM;
+ }
+ /* Digest offset must be 4 byte aligned */
+ if( MV_IS_NOT_ALIGN(pCmd->digestOffset, 4) )
+ {
+ mvOsPrintf("mvCesaAction: digestOffset %d must be 4 byte aligned\n",
+ pCmd->digestOffset);
+ return MV_BAD_PARAM;
+ }
+ /* In addition all offsets should be the same alignment: 8 or 4 */
+ if(fixOffset == 0xFF)
+ {
+ fixOffset = (pCmd->macOffset % 8);
+ }
+ else
+ {
+ if( (pCmd->macOffset % 8) != fixOffset)
+ {
+ mvOsPrintf("mvCesaAction: macOffset %d mod 8 must be equal %d\n",
+ pCmd->macOffset, fixOffset);
+ return MV_BAD_PARAM;
+ }
+ }
+ if( (pCmd->digestOffset % 8) != fixOffset)
+ {
+ mvOsPrintf("mvCesaAction: digestOffset %d mod 8 must be equal %d\n",
+ pCmd->digestOffset, fixOffset);
+ return MV_BAD_PARAM;
+ }
+ }
+ /* Check CRYPTO operation parameters */
+ if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) )
+ {
+ /* CryptoOffset should be at least 4 byte aligned */
+ if( MV_IS_NOT_ALIGN(pCmd->cryptoOffset, 4) )
+ {
+ mvOsPrintf("CesaAction: cryptoOffset=%d must be 4 byte aligned\n",
+ pCmd->cryptoOffset);
+ return MV_BAD_PARAM;
+ }
+ /* cryptoLength should be the whole number of blocks */
+ if( MV_IS_NOT_ALIGN(pCmd->cryptoLength, pSA->cryptoBlockSize) )
+ {
+ mvOsPrintf("mvCesaAction: cryptoLength=%d must be %d byte aligned\n",
+ pCmd->cryptoLength, pSA->cryptoBlockSize);
+ return MV_BAD_PARAM;
+ }
+ if(fixOffset == 0xFF)
+ {
+ fixOffset = (pCmd->cryptoOffset % 8);
+ }
+ else
+ {
+ /* In addition all offsets should be the same alignment: 8 or 4 */
+ if( (pCmd->cryptoOffset % 8) != fixOffset)
+ {
+ mvOsPrintf("mvCesaAction: cryptoOffset %d mod 8 must be equal %d \n",
+ pCmd->cryptoOffset, fixOffset);
+ return MV_BAD_PARAM;
+ }
+ }
+
+ /* check for CBC mode */
+ if(pSA->cryptoIvSize > 0)
+ {
+ /* cryptoIV must not be part of CryptoLength */
+ if( ((pCmd->ivOffset + pSA->cryptoIvSize) > pCmd->cryptoOffset) &&
+ (pCmd->ivOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) )
+ {
+ mvOsPrintf("mvCesaFragParamCheck: cryptoIvOffset (%d) is part of cryptoLength (%d+%d)\n",
+ pCmd->ivOffset, pCmd->macOffset, pCmd->macLength);
+ return MV_BAD_PARAM;
+ }
+
+ /* ivOffset must be 4 byte aligned */
+ if( MV_IS_NOT_ALIGN(pCmd->ivOffset, 4) )
+ {
+ mvOsPrintf("CesaAction: ivOffset=%d must be 4 byte aligned\n",
+ pCmd->ivOffset);
+ return MV_BAD_PARAM;
+ }
+ /* In addition all offsets should be the same alignment: 8 or 4 */
+ if( (pCmd->ivOffset % 8) != fixOffset)
+ {
+ mvOsPrintf("mvCesaAction: ivOffset %d mod 8 must be %d\n",
+ pCmd->ivOffset, fixOffset);
+ return MV_BAD_PARAM;
+ }
+ }
+ }
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaFragParamCheck -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd
+*
+* RETURN:
+* MV_STATUS
+*
+*******************************************************************************/
+static MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd)
+{
+ int offset;
+
+ if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) )
+ {
+ /* macOffset must be less that SRAM buffer size */
+ if(pCmd->macOffset > (sizeof(cesaSramVirtPtr->buf) - MV_CESA_AUTH_BLOCK_SIZE))
+ {
+ mvOsPrintf("mvCesaFragParamCheck: macOffset is too large (%d)\n",
+ pCmd->macOffset);
+ return MV_BAD_PARAM;
+ }
+ /* macOffset+macSize must be more than mbufSize - SRAM buffer size */
+ if( ((pCmd->macOffset + pCmd->macLength) > pCmd->pSrc->mbufSize) ||
+ ((pCmd->pSrc->mbufSize - (pCmd->macOffset + pCmd->macLength)) >=
+ sizeof(cesaSramVirtPtr->buf)) )
+ {
+ mvOsPrintf("mvCesaFragParamCheck: macLength is too large (%d), mbufSize=%d\n",
+ pCmd->macLength, pCmd->pSrc->mbufSize);
+ return MV_BAD_PARAM;
+ }
+ }
+
+ if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) )
+ {
+ /* cryptoOffset must be less that SRAM buffer size */
+ /* 4 for possible fixOffset */
+ if( (pCmd->cryptoOffset + 4) > (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize))
+ {
+ mvOsPrintf("mvCesaFragParamCheck: cryptoOffset is too large (%d)\n",
+ pCmd->cryptoOffset);
+ return MV_BAD_PARAM;
+ }
+
+ /* cryptoOffset+cryptoSize must be more than mbufSize - SRAM buffer size */
+ if( ((pCmd->cryptoOffset + pCmd->cryptoLength) > pCmd->pSrc->mbufSize) ||
+ ((pCmd->pSrc->mbufSize - (pCmd->cryptoOffset + pCmd->cryptoLength)) >=
+ (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize)) )
+ {
+ mvOsPrintf("mvCesaFragParamCheck: cryptoLength is too large (%d), mbufSize=%d\n",
+ pCmd->cryptoLength, pCmd->pSrc->mbufSize);
+ return MV_BAD_PARAM;
+ }
+ }
+
+ /* When MAC_THEN_CRYPTO or CRYPTO_THEN_MAC */
+ if( ((pSA->config & MV_CESA_OPERATION_MASK) ==
+ (MV_CESA_MAC_THEN_CRYPTO << MV_CESA_OPERATION_OFFSET)) ||
+ ((pSA->config & MV_CESA_OPERATION_MASK) ==
+ (MV_CESA_CRYPTO_THEN_MAC << MV_CESA_OPERATION_OFFSET)) )
+ {
+ if( (mvCtrlModelGet() == MV_5182_DEV_ID) ||
+ ( (mvCtrlModelGet() == MV_5181_DEV_ID) &&
+ (mvCtrlRevGet() >= MV_5181L_A0_REV) &&
+ (pCmd->macLength >= (1 << 14)) ) )
+ {
+ return MV_NOT_ALLOWED;
+ }
+
+ /* abs(cryptoOffset-macOffset) must be aligned cryptoBlockSize */
+ if(pCmd->cryptoOffset > pCmd->macOffset)
+ {
+ offset = pCmd->cryptoOffset - pCmd->macOffset;
+ }
+ else
+ {
+ offset = pCmd->macOffset - pCmd->cryptoOffset;
+ }
+
+ if( MV_IS_NOT_ALIGN(offset, pSA->cryptoBlockSize) )
+ {
+/*
+ mvOsPrintf("mvCesaFragParamCheck: (cryptoOffset - macOffset) must be %d byte aligned\n",
+ pSA->cryptoBlockSize);
+*/
+ return MV_NOT_ALLOWED;
+ }
+ /* Digest must not be part of CryptoLength */
+ if( ((pCmd->digestOffset + pSA->digestSize) > pCmd->cryptoOffset) &&
+ (pCmd->digestOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) )
+ {
+/*
+ mvOsPrintf("mvCesaFragParamCheck: digestOffset (%d) is part of cryptoLength (%d+%d)\n",
+ pCmd->digestOffset, pCmd->cryptoOffset, pCmd->cryptoLength);
+*/
+ return MV_NOT_ALLOWED;
+ }
+ }
+ return MV_OK;
+}
+
+/*******************************************************************************
+* mvCesaFragSizeFind -
+*
+* DESCRIPTION:
+*
+*
+* INPUT:
+* MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd,
+* int cryptoOffset, int macOffset,
+*
+* OUTPUT:
+* int* pCopySize, int* pCryptoDataSize, int* pMacDataSize
+*
+* RETURN:
+* MV_STATUS
+*
+*******************************************************************************/
+static void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq,
+ int cryptoOffset, int macOffset,
+ int* pCopySize, int* pCryptoDataSize, int* pMacDataSize)
+{
+ MV_CESA_COMMAND *pCmd = pReq->pCmd;
+ int cryptoDataSize, macDataSize, copySize;
+
+ cryptoDataSize = macDataSize = 0;
+ copySize = *pCopySize;
+
+ if( (pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ cryptoDataSize = MV_MIN( (copySize - cryptoOffset),
+ (pCmd->cryptoLength - (pReq->frags.cryptoSize + 1)) );
+
+ /* cryptoSize for each fragment must be the whole number of blocksSize */
+ if( MV_IS_NOT_ALIGN(cryptoDataSize, pSA->cryptoBlockSize) )
+ {
+ cryptoDataSize = MV_ALIGN_DOWN(cryptoDataSize, pSA->cryptoBlockSize);
+ copySize = cryptoOffset + cryptoDataSize;
+ }
+ }
+ if( (pSA->config & MV_CESA_OPERATION_MASK) !=
+ (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
+ {
+ macDataSize = MV_MIN( (copySize - macOffset),
+ (pCmd->macLength - (pReq->frags.macSize + 1)));
+
+ /* macSize for each fragment (except last) must be the whole number of blocksSize */
+ if( MV_IS_NOT_ALIGN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE) )
+ {
+ macDataSize = MV_ALIGN_DOWN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE);
+ copySize = macOffset + macDataSize;
+ }
+ cryptoDataSize = copySize - cryptoOffset;
+ }
+ *pCopySize = copySize;
+
+ if(pCryptoDataSize != NULL)
+ *pCryptoDataSize = cryptoDataSize;
+
+ if(pMacDataSize != NULL)
+ *pMacDataSize = macDataSize;
+}