openssl: replace ocf-crypto-headers with a header file from cryptodev-linux
[openwrt/openwrt.git] / target / linux / generic / files / crypto / ocf / kirkwood / cesa / mvCesa.c
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
3
4 This software file (the "File") is owned and distributed by Marvell
5 International Ltd. and/or its affiliates ("Marvell") under the following
6 alternative licensing terms. Once you have made an election to distribute the
7 File under one of the following license alternatives, please (i) delete this
8 introductory statement regarding license alternatives, (ii) delete the two
9 license alternatives that you have not elected to use and (iii) preserve the
10 Marvell copyright notice above.
11
12 ********************************************************************************
13 Marvell Commercial License Option
14
15 If you received this File from Marvell and you have entered into a commercial
16 license agreement (a "Commercial License") with Marvell, the File is licensed
17 to you under the terms of the applicable Commercial License.
18
19 ********************************************************************************
20 Marvell GPL License Option
21
22 If you received this File from Marvell, you may opt to use, redistribute and/or
23 modify this File in accordance with the terms and conditions of the General
24 Public License Version 2, June 1991 (the "GPL License"), a copy of which is
25 available along with the File in the license.txt file or by writing to the Free
26 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
27 on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
28
29 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
31 DISCLAIMED. The GPL License provides additional details about this warranty
32 disclaimer.
33 ********************************************************************************
34 Marvell BSD License Option
35
36 If you received this File from Marvell, you may opt to use, redistribute and/or
37 modify this File under the following licensing terms.
38 Redistribution and use in source and binary forms, with or without modification,
39 are permitted provided that the following conditions are met:
40
41 * Redistributions of source code must retain the above copyright notice,
42 this list of conditions and the following disclaimer.
43
44 * Redistributions in binary form must reproduce the above copyright
45 notice, this list of conditions and the following disclaimer in the
46 documentation and/or other materials provided with the distribution.
47
48 * Neither the name of Marvell nor the names of its contributors may be
49 used to endorse or promote products derived from this software without
50 specific prior written permission.
51
52 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
53 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
56 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
59 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
61 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
63 *******************************************************************************/
64
65 #include "cesa/mvCesa.h"
66
67 #include "ctrlEnv/mvCtrlEnvLib.h"
68 #undef CESA_DEBUG
69
70
71 /********** Global variables **********/
72
73 /* If request size is more than MV_CESA_MAX_BUF_SIZE the
74 * request is processed as fragmented request.
75 */
76
77 MV_CESA_STATS cesaStats;
78
79 MV_BUF_INFO cesaSramSaBuf;
80 short cesaLastSid = -1;
81 MV_CESA_SA* pCesaSAD = NULL;
82 MV_U16 cesaMaxSA = 0;
83
84 MV_CESA_REQ* pCesaReqFirst = NULL;
85 MV_CESA_REQ* pCesaReqLast = NULL;
86 MV_CESA_REQ* pCesaReqEmpty = NULL;
87 MV_CESA_REQ* pCesaReqProcess = NULL;
88 int cesaQueueDepth = 0;
89 int cesaReqResources = 0;
90
91 MV_CESA_SRAM_MAP* cesaSramVirtPtr = NULL;
92 MV_U32 cesaCryptEngBase = 0;
93 void *cesaOsHandle = NULL;
94 #if (MV_CESA_VERSION >= 3)
95 MV_U32 cesaChainLength = 0;
96 int chainReqNum = 0;
97 MV_U32 chainIndex = 0;
98 MV_CESA_REQ* pNextActiveChain = 0;
99 MV_CESA_REQ* pEndCurrChain = 0;
100 MV_BOOL isFirstReq = MV_TRUE;
101 #endif
102
103 static INLINE MV_U8* mvCesaSramAddrGet(void)
104 {
105 #ifdef MV_CESA_NO_SRAM
106 return (MV_U8*)cesaSramVirtPtr;
107 #else
108 return (MV_U8*)cesaCryptEngBase;
109 #endif /* MV_CESA_NO_SRAM */
110 }
111
112 static INLINE MV_ULONG mvCesaSramVirtToPhys(void* pDev, MV_U8* pSramVirt)
113 {
114 #ifdef MV_CESA_NO_SRAM
115 return (MV_ULONG)mvOsIoVirtToPhy(NULL, pSramVirt);
116 #else
117 return (MV_ULONG)pSramVirt;
118 #endif /* MV_CESA_NO_SRAM */
119 }
120
121 /* Internal Function prototypes */
122
123 static INLINE void mvCesaSramDescrBuild(MV_U32 config, int frag,
124 int cryptoOffset, int ivOffset, int cryptoLength,
125 int macOffset, int digestOffset, int macLength, int macTotalLen,
126 MV_CESA_REQ *pCesaReq, MV_DMA_DESC* pDmaDesc);
127
128 static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc);
129
130 static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
131 MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
132 int offset, int copySize, MV_BOOL skipFlush);
133
134 static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
135 unsigned char innerIV[], unsigned char outerIV[]);
136
137 static MV_STATUS mvCesaFragAuthComplete(MV_CESA_REQ* pReq, MV_CESA_SA* pSA,
138 int macDataSize);
139
140 static MV_CESA_COMMAND* mvCesaCtrModeInit(void);
141
142 static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd);
143 static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd);
144 static void mvCesaCtrModeFinish(MV_CESA_COMMAND *pCmd);
145
146 static INLINE MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq);
147 static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag);
148
149 static INLINE MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset);
150 static INLINE MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd);
151
152 static INLINE void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq,
153 int cryptoOffset, int macOffset,
154 int* pCopySize, int* pCryptoDataSize, int* pMacDataSize);
155 static MV_STATUS mvCesaMbufCacheUnmap(MV_CESA_MBUF* pMbuf, int offset, int size);
156
157
158 /* Go to the next request in the request queue */
159 static INLINE MV_CESA_REQ* MV_CESA_REQ_NEXT_PTR(MV_CESA_REQ* pReq)
160 {
161 if(pReq == pCesaReqLast)
162 return pCesaReqFirst;
163
164 return pReq+1;
165 }
166
167 #if (MV_CESA_VERSION >= 3)
168 /* Go to the previous request in the request queue */
169 static INLINE MV_CESA_REQ* MV_CESA_REQ_PREV_PTR(MV_CESA_REQ* pReq)
170 {
171 if(pReq == pCesaReqFirst)
172 return pCesaReqLast;
173
174 return pReq-1;
175 }
176
177 #endif
178
179
180 static INLINE void mvCesaReqProcessStart(MV_CESA_REQ* pReq)
181 {
182 int frag;
183
184 #if (MV_CESA_VERSION >= 3)
185 pReq->state = MV_CESA_CHAIN;
186 #else
187 pReq->state = MV_CESA_PROCESS;
188 #endif
189 cesaStats.startCount++;
190
191 if(pReq->fragMode == MV_CESA_FRAG_NONE)
192 {
193 frag = 0;
194 }
195 else
196 {
197 frag = pReq->frags.nextFrag;
198 pReq->frags.nextFrag++;
199 }
200 #if (MV_CESA_VERSION >= 2)
201 /* Enable TDMA engine */
202 MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0);
203 MV_REG_WRITE(MV_CESA_TDMA_NEXT_DESC_PTR_REG,
204 (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
205 #else
206 /* Enable IDMA engine */
207 MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0);
208 MV_REG_WRITE(IDMA_NEXT_DESC_PTR_REG(0),
209 (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
210 #endif /* MV_CESA_VERSION >= 2 */
211
212 #if defined(MV_BRIDGE_SYNC_REORDER)
213 mvOsBridgeReorderWA();
214 #endif
215
216 /* Start Accelerator */
217 MV_REG_WRITE(MV_CESA_CMD_REG, MV_CESA_CMD_CHAN_ENABLE_MASK);
218 }
219
220
221 /*******************************************************************************
222 * mvCesaHalInit - Initialize the CESA driver
223 *
224 * DESCRIPTION:
225 * This function initialize the CESA driver.
226 * 1) Session database
227 * 2) Request queue
228 * 4) DMA descriptor lists - one list per request. Each list
229 * has MV_CESA_MAX_DMA_DESC descriptors.
230 *
231 * INPUT:
232 * numOfSession - maximum number of supported sessions
233 * queueDepth - number of elements in the request queue.
234 * pSramBase - virtual address of Sram
235 * osHandle - A handle used by the OS to allocate memory for the
236 * module (Passed to the OS Services layer)
237 *
238 * RETURN:
239 * MV_OK - Success
240 * MV_NO_RESOURCE - Fail, can't allocate resources:
241 * Session database, request queue,
242 * DMA descriptors list, LRU cache database.
243 * MV_NOT_ALIGNED - Sram base address is not 8 byte aligned.
244 *
245 *******************************************************************************/
246 MV_STATUS mvCesaHalInit (int numOfSession, int queueDepth, char* pSramBase, MV_U32 cryptEngBase,
247 void *osHandle)
248 {
249 int i, req;
250 MV_U32 descOffsetReg, configReg;
251 MV_CESA_SRAM_SA *pSramSA;
252
253
254 mvOsPrintf("mvCesaInit: sessions=%d, queue=%d, pSram=%p\n",
255 numOfSession, queueDepth, pSramBase);
256
257 cesaOsHandle = osHandle;
258 /* Create Session database */
259 pCesaSAD = mvOsMalloc(sizeof(MV_CESA_SA)*numOfSession);
260 if(pCesaSAD == NULL)
261 {
262 mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d SAs\n",
263 sizeof(MV_CESA_SA)*numOfSession, numOfSession);
264 mvCesaFinish();
265 return MV_NO_RESOURCE;
266 }
267 memset(pCesaSAD, 0, sizeof(MV_CESA_SA)*numOfSession);
268 cesaMaxSA = numOfSession;
269
270 /* Allocate imag of sramSA in the DRAM */
271 cesaSramSaBuf.bufSize = sizeof(MV_CESA_SRAM_SA)*numOfSession +
272 CPU_D_CACHE_LINE_SIZE;
273
274 cesaSramSaBuf.bufVirtPtr = mvOsIoCachedMalloc(osHandle,cesaSramSaBuf.bufSize,
275 &cesaSramSaBuf.bufPhysAddr,
276 &cesaSramSaBuf.memHandle);
277
278 if(cesaSramSaBuf.bufVirtPtr == NULL)
279 {
280 mvOsPrintf("mvCesaInit: Can't allocate %d bytes for sramSA structures\n",
281 cesaSramSaBuf.bufSize);
282 mvCesaFinish();
283 return MV_NO_RESOURCE;
284 }
285 memset(cesaSramSaBuf.bufVirtPtr, 0, cesaSramSaBuf.bufSize);
286 pSramSA = (MV_CESA_SRAM_SA*)MV_ALIGN_UP((MV_ULONG)cesaSramSaBuf.bufVirtPtr,
287 CPU_D_CACHE_LINE_SIZE);
288 for(i=0; i<numOfSession; i++)
289 {
290 pCesaSAD[i].pSramSA = &pSramSA[i];
291 }
292
293 /* Create request queue */
294 pCesaReqFirst = mvOsMalloc(sizeof(MV_CESA_REQ)*queueDepth);
295 if(pCesaReqFirst == NULL)
296 {
297 mvOsPrintf("mvCesaInit: Can't allocate %u bytes for %d requests\n",
298 sizeof(MV_CESA_REQ)*queueDepth, queueDepth);
299 mvCesaFinish();
300 return MV_NO_RESOURCE;
301 }
302 memset(pCesaReqFirst, 0, sizeof(MV_CESA_REQ)*queueDepth);
303 pCesaReqEmpty = pCesaReqFirst;
304 pCesaReqLast = pCesaReqFirst + (queueDepth-1);
305 pCesaReqProcess = pCesaReqEmpty;
306 cesaQueueDepth = queueDepth;
307 cesaReqResources = queueDepth;
308 #if (MV_CESA_VERSION >= 3)
309 cesaChainLength = MAX_CESA_CHAIN_LENGTH;
310 #endif
311 /* pSramBase must be 8 byte aligned */
312 if( MV_IS_NOT_ALIGN((MV_ULONG)pSramBase, 8) )
313 {
314 mvOsPrintf("mvCesaInit: pSramBase (%p) must be 8 byte aligned\n",
315 pSramBase);
316 mvCesaFinish();
317 return MV_NOT_ALIGNED;
318 }
319 cesaSramVirtPtr = (MV_CESA_SRAM_MAP*)pSramBase;
320
321 cesaCryptEngBase = cryptEngBase;
322
323 /*memset(cesaSramVirtPtr, 0, sizeof(MV_CESA_SRAM_MAP));*/
324
325 /* Clear registers */
326 MV_REG_WRITE( MV_CESA_CFG_REG, 0);
327 MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
328 MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
329
330 /* Initialize DMA descriptor lists for all requests in Request queue */
331 descOffsetReg = configReg = 0;
332 for(req=0; req<queueDepth; req++)
333 {
334 int frag;
335 MV_CESA_REQ* pReq;
336 MV_DMA_DESC* pDmaDesc;
337
338 pReq = &pCesaReqFirst[req];
339
340 pReq->cesaDescBuf.bufSize = sizeof(MV_CESA_DESC)*MV_CESA_MAX_REQ_FRAGS +
341 CPU_D_CACHE_LINE_SIZE;
342
343 pReq->cesaDescBuf.bufVirtPtr =
344 mvOsIoCachedMalloc(osHandle,pReq->cesaDescBuf.bufSize,
345 &pReq->cesaDescBuf.bufPhysAddr,
346 &pReq->cesaDescBuf.memHandle);
347
348 if(pReq->cesaDescBuf.bufVirtPtr == NULL)
349 {
350 mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for CESA descriptors\n",
351 req, pReq->cesaDescBuf.bufSize);
352 mvCesaFinish();
353 return MV_NO_RESOURCE;
354 }
355 memset(pReq->cesaDescBuf.bufVirtPtr, 0, pReq->cesaDescBuf.bufSize);
356 pReq->pCesaDesc = (MV_CESA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->cesaDescBuf.bufVirtPtr,
357 CPU_D_CACHE_LINE_SIZE);
358
359 pReq->dmaDescBuf.bufSize = sizeof(MV_DMA_DESC)*MV_CESA_MAX_DMA_DESC*MV_CESA_MAX_REQ_FRAGS +
360 CPU_D_CACHE_LINE_SIZE;
361
362 pReq->dmaDescBuf.bufVirtPtr =
363 mvOsIoCachedMalloc(osHandle,pReq->dmaDescBuf.bufSize,
364 &pReq->dmaDescBuf.bufPhysAddr,
365 &pReq->dmaDescBuf.memHandle);
366
367 if(pReq->dmaDescBuf.bufVirtPtr == NULL)
368 {
369 mvOsPrintf("mvCesaInit: req=%d, Can't allocate %d bytes for DMA descriptor list\n",
370 req, pReq->dmaDescBuf.bufSize);
371 mvCesaFinish();
372 return MV_NO_RESOURCE;
373 }
374 memset(pReq->dmaDescBuf.bufVirtPtr, 0, pReq->dmaDescBuf.bufSize);
375 pDmaDesc = (MV_DMA_DESC*)MV_ALIGN_UP((MV_ULONG)pReq->dmaDescBuf.bufVirtPtr,
376 CPU_D_CACHE_LINE_SIZE);
377
378 for(frag=0; frag<MV_CESA_MAX_REQ_FRAGS; frag++)
379 {
380 MV_CESA_DMA* pDma = &pReq->dma[frag];
381
382 pDma->pDmaFirst = pDmaDesc;
383 pDma->pDmaLast = NULL;
384
385 for(i=0; i<MV_CESA_MAX_DMA_DESC-1; i++)
386 {
387 /* link all DMA descriptors together */
388 pDma->pDmaFirst[i].phyNextDescPtr =
389 MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pDmaDesc[i+1]));
390 }
391 pDma->pDmaFirst[i].phyNextDescPtr = 0;
392 mvOsCacheFlush(NULL, &pDma->pDmaFirst[0], MV_CESA_MAX_DMA_DESC*sizeof(MV_DMA_DESC));
393
394 pDmaDesc += MV_CESA_MAX_DMA_DESC;
395 }
396 }
397 /*mvCesaCryptoIvSet(NULL, MV_CESA_MAX_IV_LENGTH);*/
398 descOffsetReg = (MV_U16)((MV_U8*)&cesaSramVirtPtr->desc - mvCesaSramAddrGet());
399 MV_REG_WRITE(MV_CESA_CHAN_DESC_OFFSET_REG, descOffsetReg);
400
401 configReg |= (MV_CESA_CFG_WAIT_DMA_MASK | MV_CESA_CFG_ACT_DMA_MASK);
402 #if (MV_CESA_VERSION >= 3)
403 configReg |= MV_CESA_CFG_CHAIN_MODE_MASK;
404 #endif
405
406 #if (MV_CESA_VERSION >= 2)
407 /* Initialize TDMA engine */
408 MV_REG_WRITE(MV_CESA_TDMA_CTRL_REG, MV_CESA_TDMA_CTRL_VALUE);
409 MV_REG_WRITE(MV_CESA_TDMA_BYTE_COUNT_REG, 0);
410 MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0);
411 #else
412 /* Initialize IDMA #0 engine */
413 MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0);
414 MV_REG_WRITE(IDMA_BYTE_COUNT_REG(0), 0);
415 MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0);
416 MV_REG_WRITE(IDMA_CTRL_HIGH_REG(0), ICCHR_ENDIAN_LITTLE
417 #ifdef MV_CPU_LE
418 | ICCHR_DESC_BYTE_SWAP_EN
419 #endif
420 );
421 /* Clear Cause Byte of IDMA channel to be used */
422 MV_REG_WRITE( IDMA_CAUSE_REG, ~ICICR_CAUSE_MASK_ALL(0));
423 MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), MV_CESA_IDMA_CTRL_LOW_VALUE);
424 #endif /* (MV_CESA_VERSION >= 2) */
425
426 /* Set CESA configuration registers */
427 MV_REG_WRITE( MV_CESA_CFG_REG, configReg);
428 mvCesaDebugStatsClear();
429
430 return MV_OK;
431 }
432
433 /*******************************************************************************
434 * mvCesaFinish - Shutdown the CESA driver
435 *
436 * DESCRIPTION:
437 * This function shutdown the CESA driver and free all allocted resources.
438 *
439 * INPUT: None
440 *
441 * RETURN:
442 * MV_OK - Success
443 * Other - Fail
444 *
445 *******************************************************************************/
446 MV_STATUS mvCesaFinish (void)
447 {
448 int req;
449 MV_CESA_REQ* pReq;
450
451 mvOsPrintf("mvCesaFinish: \n");
452
453 cesaSramVirtPtr = NULL;
454
455 /* Free all resources: DMA list, etc. */
456 for(req=0; req<cesaQueueDepth; req++)
457 {
458 pReq = &pCesaReqFirst[req];
459 if(pReq->dmaDescBuf.bufVirtPtr != NULL)
460 {
461 mvOsIoCachedFree(cesaOsHandle,pReq->dmaDescBuf.bufSize,
462 pReq->dmaDescBuf.bufPhysAddr,
463 pReq->dmaDescBuf.bufVirtPtr,
464 pReq->dmaDescBuf.memHandle);
465 }
466 if(pReq->cesaDescBuf.bufVirtPtr != NULL)
467 {
468 mvOsIoCachedFree(cesaOsHandle,pReq->cesaDescBuf.bufSize,
469 pReq->cesaDescBuf.bufPhysAddr,
470 pReq->cesaDescBuf.bufVirtPtr,
471 pReq->cesaDescBuf.memHandle);
472 }
473 }
474 #if (MV_CESA_VERSION < 2)
475 MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0);
476 #endif /* (MV_CESA_VERSION < 2) */
477
478 /* Free request queue */
479 if(pCesaReqFirst != NULL)
480 {
481 mvOsFree(pCesaReqFirst);
482 pCesaReqFirst = pCesaReqLast = NULL;
483 pCesaReqEmpty = pCesaReqProcess = NULL;
484 cesaQueueDepth = cesaReqResources = 0;
485 }
486 /* Free SA database */
487 if(pCesaSAD != NULL)
488 {
489 mvOsFree(pCesaSAD);
490 pCesaSAD = NULL;
491 cesaMaxSA = 0;
492 }
493 MV_REG_WRITE( MV_CESA_CFG_REG, 0);
494 MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
495 MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
496
497 return MV_OK;
498 }
499
500 /*******************************************************************************
501 * mvCesaCryptoIvSet - Set IV value for Crypto algorithm working in CBC mode
502 *
503 * DESCRIPTION:
504 * This function set IV value using by Crypto algorithms in CBC mode.
505 * Each channel has its own IV value.
506 * This function gets IV value from the caller. If no IV value passed from
507 * the caller or only part of IV passed, the function will init the rest part
508 * of IV value (or the whole IV) by random value.
509 *
510 * INPUT:
511 * MV_U8* pIV - Pointer to IV value supplied by user. If pIV==NULL
512 * the function will generate random IV value.
513 * int ivSize - size (in bytes) of IV provided by user. If ivSize is
514 * smaller than maximum IV size, the function will complete
515 * IV by random value.
516 *
517 * RETURN:
518 * MV_OK - Success
519 * Other - Fail
520 *
521 *******************************************************************************/
522 MV_STATUS mvCesaCryptoIvSet(MV_U8* pIV, int ivSize)
523 {
524 MV_U8* pSramIV;
525 #if defined(MV646xx)
526 mvOsPrintf("mvCesaCryptoIvSet: ERR. shouldn't use this call on MV64660\n");
527 #endif
528 pSramIV = cesaSramVirtPtr->cryptoIV;
529 if(ivSize > MV_CESA_MAX_IV_LENGTH)
530 {
531 mvOsPrintf("mvCesaCryptoIvSet: ivSize (%d) is too large\n", ivSize);
532 ivSize = MV_CESA_MAX_IV_LENGTH;
533 }
534 if(pIV != NULL)
535 {
536 memcpy(pSramIV, pIV, ivSize);
537 ivSize = MV_CESA_MAX_IV_LENGTH - ivSize;
538 pSramIV += ivSize;
539 }
540
541 while(ivSize > 0)
542 {
543 int size, mv_random = mvOsRand();
544
545 size = MV_MIN(ivSize, sizeof(mv_random));
546 memcpy(pSramIV, (void*)&mv_random, size);
547
548 pSramIV += size;
549 ivSize -= size;
550 }
551 /*
552 mvOsCacheFlush(NULL, cesaSramVirtPtr->cryptoIV,
553 MV_CESA_MAX_IV_LENGTH);
554 mvOsCacheInvalidate(NULL, cesaSramVirtPtr->cryptoIV,
555 MV_CESA_MAX_IV_LENGTH);
556 */
557 return MV_OK;
558 }
559
560 /*******************************************************************************
561 * mvCesaSessionOpen - Open new uni-directional crypto session
562 *
563 * DESCRIPTION:
564 * This function open new session.
565 *
566 * INPUT:
567 * MV_CESA_OPEN_SESSION *pSession - pointer to new session input parameters
568 *
569 * OUTPUT:
570 * short *pSid - session ID, should be used for all future
571 * requests over this session.
572 *
573 * RETURN:
574 * MV_OK - Session opend successfully.
575 * MV_FULL - All sessions are in use, no free place in
576 * SA database.
577 * MV_BAD_PARAM - One of session input parameters is invalid.
578 *
579 *******************************************************************************/
580 MV_STATUS mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short* pSid)
581 {
582 short sid;
583 MV_U32 config = 0;
584 int digestSize;
585
586 cesaStats.openedCount++;
587
588 /* Find free entry in SAD */
589 for(sid=0; sid<cesaMaxSA; sid++)
590 {
591 if(pCesaSAD[sid].valid == 0)
592 {
593 break;
594 }
595 }
596 if(sid == cesaMaxSA)
597 {
598 mvOsPrintf("mvCesaSessionOpen: SA Database is FULL\n");
599 return MV_FULL;
600 }
601
602 /* Check Input parameters for Open session */
603 if (pSession->operation >= MV_CESA_MAX_OPERATION)
604 {
605 mvOsPrintf("mvCesaSessionOpen: Unexpected operation %d\n",
606 pSession->operation);
607 return MV_BAD_PARAM;
608 }
609 config |= (pSession->operation << MV_CESA_OPERATION_OFFSET);
610
611 if( (pSession->direction != MV_CESA_DIR_ENCODE) &&
612 (pSession->direction != MV_CESA_DIR_DECODE) )
613 {
614 mvOsPrintf("mvCesaSessionOpen: Unexpected direction %d\n",
615 pSession->direction);
616 return MV_BAD_PARAM;
617 }
618 config |= (pSession->direction << MV_CESA_DIRECTION_BIT);
619 /* Clear SA entry */
620 /* memset(&pCesaSAD[sid], 0, sizeof(pCesaSAD[sid])); */
621
622 /* Check AUTH parameters and update SA entry */
623 if(pSession->operation != MV_CESA_CRYPTO_ONLY)
624 {
625 /* For HMAC (MD5 and SHA1) - Maximum Key size is 64 bytes */
626 if( (pSession->macMode == MV_CESA_MAC_HMAC_MD5) ||
627 (pSession->macMode == MV_CESA_MAC_HMAC_SHA1) )
628 {
629 if(pSession->macKeyLength > MV_CESA_MAX_MAC_KEY_LENGTH)
630 {
631 mvOsPrintf("mvCesaSessionOpen: macKeyLength %d is too large\n",
632 pSession->macKeyLength);
633 return MV_BAD_PARAM;
634 }
635 mvCesaHmacIvGet(pSession->macMode, pSession->macKey, pSession->macKeyLength,
636 pCesaSAD[sid].pSramSA->macInnerIV,
637 pCesaSAD[sid].pSramSA->macOuterIV);
638 pCesaSAD[sid].macKeyLength = pSession->macKeyLength;
639 }
640 switch(pSession->macMode)
641 {
642 case MV_CESA_MAC_MD5:
643 case MV_CESA_MAC_HMAC_MD5:
644 digestSize = MV_CESA_MD5_DIGEST_SIZE;
645 break;
646
647 case MV_CESA_MAC_SHA1:
648 case MV_CESA_MAC_HMAC_SHA1:
649 digestSize = MV_CESA_SHA1_DIGEST_SIZE;
650 break;
651
652 default:
653 mvOsPrintf("mvCesaSessionOpen: Unexpected macMode %d\n",
654 pSession->macMode);
655 return MV_BAD_PARAM;
656 }
657 config |= (pSession->macMode << MV_CESA_MAC_MODE_OFFSET);
658
659 /* Supported digest sizes: MD5 - 16 bytes (128 bits), */
660 /* SHA1 - 20 bytes (160 bits) or 12 bytes (96 bits) for both */
661 if( (pSession->digestSize != digestSize) && (pSession->digestSize != 12))
662 {
663 mvOsPrintf("mvCesaSessionOpen: Unexpected digest size %d\n",
664 pSession->digestSize);
665 mvOsPrintf("\t Valid values [bytes]: MD5-16, SHA1-20, Both-12\n");
666 return MV_BAD_PARAM;
667 }
668 pCesaSAD[sid].digestSize = pSession->digestSize;
669
670 if(pCesaSAD[sid].digestSize == 12)
671 {
672 /* Set MV_CESA_MAC_DIGEST_SIZE_BIT if digest size is 96 bits */
673 config |= (MV_CESA_MAC_DIGEST_96B << MV_CESA_MAC_DIGEST_SIZE_BIT);
674 }
675 }
676
677 /* Check CRYPTO parameters and update SA entry */
678 if(pSession->operation != MV_CESA_MAC_ONLY)
679 {
680 switch(pSession->cryptoAlgorithm)
681 {
682 case MV_CESA_CRYPTO_DES:
683 pCesaSAD[sid].cryptoKeyLength = MV_CESA_DES_KEY_LENGTH;
684 pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE;
685 break;
686
687 case MV_CESA_CRYPTO_3DES:
688 pCesaSAD[sid].cryptoKeyLength = MV_CESA_3DES_KEY_LENGTH;
689 pCesaSAD[sid].cryptoBlockSize = MV_CESA_DES_BLOCK_SIZE;
690 /* Only EDE mode is supported */
691 config |= (MV_CESA_CRYPTO_3DES_EDE <<
692 MV_CESA_CRYPTO_3DES_MODE_BIT);
693 break;
694
695 case MV_CESA_CRYPTO_AES:
696 switch(pSession->cryptoKeyLength)
697 {
698 case 16:
699 pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_128_KEY_LENGTH;
700 config |= (MV_CESA_CRYPTO_AES_KEY_128 <<
701 MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
702 break;
703
704 case 24:
705 pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_192_KEY_LENGTH;
706 config |= (MV_CESA_CRYPTO_AES_KEY_192 <<
707 MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
708 break;
709
710 case 32:
711 default:
712 pCesaSAD[sid].cryptoKeyLength = MV_CESA_AES_256_KEY_LENGTH;
713 config |= (MV_CESA_CRYPTO_AES_KEY_256 <<
714 MV_CESA_CRYPTO_AES_KEY_LEN_OFFSET);
715 break;
716 }
717 pCesaSAD[sid].cryptoBlockSize = MV_CESA_AES_BLOCK_SIZE;
718 break;
719
720 default:
721 mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoAlgorithm %d\n",
722 pSession->cryptoAlgorithm);
723 return MV_BAD_PARAM;
724 }
725 config |= (pSession->cryptoAlgorithm << MV_CESA_CRYPTO_ALG_OFFSET);
726
727 if(pSession->cryptoKeyLength != pCesaSAD[sid].cryptoKeyLength)
728 {
729 mvOsPrintf("cesaSessionOpen: Wrong CryptoKeySize %d != %d\n",
730 pSession->cryptoKeyLength, pCesaSAD[sid].cryptoKeyLength);
731 return MV_BAD_PARAM;
732 }
733
734 /* Copy Crypto key */
735 if( (pSession->cryptoAlgorithm == MV_CESA_CRYPTO_AES) &&
736 (pSession->direction == MV_CESA_DIR_DECODE))
737 {
738 /* Crypto Key for AES decode is computed from original key material */
739 /* and depend on cryptoKeyLength (128/192/256 bits) */
740 aesMakeKey(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey,
741 pSession->cryptoKeyLength*8, MV_CESA_AES_BLOCK_SIZE*8);
742 }
743 else
744 {
745 /*panic("mvCesaSessionOpen2");*/
746 memcpy(pCesaSAD[sid].pSramSA->cryptoKey, pSession->cryptoKey,
747 pCesaSAD[sid].cryptoKeyLength);
748
749 }
750
751 switch(pSession->cryptoMode)
752 {
753 case MV_CESA_CRYPTO_ECB:
754 pCesaSAD[sid].cryptoIvSize = 0;
755 break;
756
757 case MV_CESA_CRYPTO_CBC:
758 pCesaSAD[sid].cryptoIvSize = pCesaSAD[sid].cryptoBlockSize;
759 break;
760
761 case MV_CESA_CRYPTO_CTR:
762 /* Supported only for AES algorithm */
763 if(pSession->cryptoAlgorithm != MV_CESA_CRYPTO_AES)
764 {
765 mvOsPrintf("mvCesaSessionOpen: CRYPTO CTR mode supported for AES only\n");
766 return MV_BAD_PARAM;
767 }
768 pCesaSAD[sid].cryptoIvSize = 0;
769 pCesaSAD[sid].ctrMode = 1;
770 /* Replace to ECB mode for HW */
771 pSession->cryptoMode = MV_CESA_CRYPTO_ECB;
772 break;
773
774 default:
775 mvOsPrintf("mvCesaSessionOpen: Unexpected cryptoMode %d\n",
776 pSession->cryptoMode);
777 return MV_BAD_PARAM;
778 }
779
780 config |= (pSession->cryptoMode << MV_CESA_CRYPTO_MODE_BIT);
781 }
782 pCesaSAD[sid].config = config;
783
784 mvOsCacheFlush(NULL, pCesaSAD[sid].pSramSA, sizeof(MV_CESA_SRAM_SA));
785 if(pSid != NULL)
786 *pSid = sid;
787
788 pCesaSAD[sid].valid = 1;
789 return MV_OK;
790 }
791
792 /*******************************************************************************
793 * mvCesaSessionClose - Close active crypto session
794 *
795 * DESCRIPTION:
796 * This function closes existing session
797 *
798 * INPUT:
799 * short sid - Unique identifier of the session to be closed
800 *
801 * RETURN:
802 * MV_OK - Session closed successfully.
803 * MV_BAD_PARAM - Session identifier is out of valid range.
804 * MV_NOT_FOUND - There is no active session with such ID.
805 *
806 *******************************************************************************/
807 MV_STATUS mvCesaSessionClose(short sid)
808 {
809 cesaStats.closedCount++;
810
811 if(sid >= cesaMaxSA)
812 {
813 mvOsPrintf("CESA Error: sid (%d) is too big\n", sid);
814 return MV_BAD_PARAM;
815 }
816 if(pCesaSAD[sid].valid == 0)
817 {
818 mvOsPrintf("CESA Warning: Session (sid=%d) is invalid\n", sid);
819 return MV_NOT_FOUND;
820 }
821 if(cesaLastSid == sid)
822 cesaLastSid = -1;
823
824 pCesaSAD[sid].valid = 0;
825 return MV_OK;
826 }
827
828 /*******************************************************************************
829 * mvCesaAction - Perform crypto operation
830 *
831 * DESCRIPTION:
832 * This function set new CESA request FIFO queue for further HW processing.
833 * The function checks request parameters before set new request to the queue.
834 * If one of the CESA channels is ready for processing the request will be
835 * passed to HW. When request processing is finished the CESA interrupt will
836 * be generated by HW. The caller should call mvCesaReadyGet() function to
837 * complete request processing and get result.
838 *
839 * INPUT:
840 * MV_CESA_COMMAND *pCmd - pointer to new CESA request.
841 * It includes pointers to Source and Destination
842 * buffers, session identifier get from
843 * mvCesaSessionOpen() function, pointer to caller
844 * private data and all needed crypto parameters.
845 *
846 * RETURN:
847 * MV_OK - request successfully added to request queue
848 * and will be processed.
849 * MV_NO_MORE - request successfully added to request queue and will
850 * be processed, but request queue became Full and next
851 * request will not be accepted.
852 * MV_NO_RESOURCE - request queue is FULL and the request can not
853 * be processed.
854 * MV_OUT_OF_CPU_MEM - memory allocation needed for request processing is
855 * failed. Request can not be processed.
856 * MV_NOT_ALLOWED - This mixed request (CRYPTO+MAC) can not be processed
857 * as one request and should be splitted for two requests:
858 * CRYPTO_ONLY and MAC_ONLY.
859 * MV_BAD_PARAM - One of the request parameters is out of valid range.
860 * The request can not be processed.
861 *
862 *******************************************************************************/
863 MV_STATUS mvCesaAction (MV_CESA_COMMAND *pCmd)
864 {
865 MV_STATUS status;
866 MV_CESA_REQ* pReq = pCesaReqEmpty;
867 int sid = pCmd->sessionId;
868 MV_CESA_SA* pSA = &pCesaSAD[sid];
869 #if (MV_CESA_VERSION >= 3)
870 MV_CESA_REQ* pFromReq;
871 MV_CESA_REQ* pToReq;
872 #endif
873 cesaStats.reqCount++;
874
875 /* Check that the request queue is not FULL */
876 if(cesaReqResources == 0)
877 return MV_NO_RESOURCE;
878
879 if( (sid >= cesaMaxSA) || (!pSA->valid) )
880 {
881 mvOsPrintf("CESA Action Error: Session sid=%d is INVALID\n", sid);
882 return MV_BAD_PARAM;
883 }
884 pSA->count++;
885
886 if(pSA->ctrMode)
887 {
888 /* AES in CTR mode can't be mixed with Authentication */
889 if( (pSA->config & MV_CESA_OPERATION_MASK) !=
890 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
891 {
892 mvOsPrintf("mvCesaAction : CRYPTO CTR mode can't be mixed with AUTH\n");
893 return MV_NOT_ALLOWED;
894 }
895 /* All other request parameters should not be checked because key stream */
896 /* (not user data) processed by AES HW engine */
897 pReq->pOrgCmd = pCmd;
898 /* Allocate temporary pCmd structure for Key stream */
899 pCmd = mvCesaCtrModeInit();
900 if(pCmd == NULL)
901 return MV_OUT_OF_CPU_MEM;
902
903 /* Prepare Key stream */
904 mvCesaCtrModePrepare(pCmd, pReq->pOrgCmd);
905 pReq->fixOffset = 0;
906 }
907 else
908 {
909 /* Check request parameters and calculae fixOffset */
910 status = mvCesaParamCheck(pSA, pCmd, &pReq->fixOffset);
911 if(status != MV_OK)
912 {
913 return status;
914 }
915 }
916 pReq->pCmd = pCmd;
917
918 /* Check if the packet need fragmentation */
919 if(pCmd->pSrc->mbufSize <= sizeof(cesaSramVirtPtr->buf) )
920 {
921 /* request size is smaller than single buffer size */
922 pReq->fragMode = MV_CESA_FRAG_NONE;
923
924 /* Prepare NOT fragmented packets */
925 status = mvCesaReqProcess(pReq);
926 if(status != MV_OK)
927 {
928 mvOsPrintf("CesaReady: ReqProcess error: pReq=%p, status=0x%x\n",
929 pReq, status);
930 }
931 #if (MV_CESA_VERSION >= 3)
932 pReq->frags.numFrag = 1;
933 #endif
934 }
935 else
936 {
937 MV_U8 frag = 0;
938
939 /* request size is larger than buffer size - needs fragmentation */
940
941 /* Check restrictions for processing fragmented packets */
942 status = mvCesaFragParamCheck(pSA, pCmd);
943 if(status != MV_OK)
944 return status;
945
946 pReq->fragMode = MV_CESA_FRAG_FIRST;
947 pReq->frags.nextFrag = 0;
948
949 /* Prepare Process Fragmented packets */
950 while(pReq->fragMode != MV_CESA_FRAG_LAST)
951 {
952 if(frag >= MV_CESA_MAX_REQ_FRAGS)
953 {
954 mvOsPrintf("mvCesaAction Error: Too large request frag=%d\n", frag);
955 return MV_OUT_OF_CPU_MEM;
956 }
957 status = mvCesaFragReqProcess(pReq, frag);
958 if(status == MV_OK) {
959 #if (MV_CESA_VERSION >= 3)
960 if(frag) {
961 pReq->dma[frag-1].pDmaLast->phyNextDescPtr =
962 MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
963 mvOsCacheFlush(NULL, pReq->dma[frag-1].pDmaLast, sizeof(MV_DMA_DESC));
964 }
965 #endif
966 frag++;
967 }
968 }
969 pReq->frags.numFrag = frag;
970 #if (MV_CESA_VERSION >= 3)
971 if(chainReqNum) {
972 chainReqNum += pReq->frags.numFrag;
973 if(chainReqNum >= MAX_CESA_CHAIN_LENGTH)
974 chainReqNum = MAX_CESA_CHAIN_LENGTH;
975 }
976 #endif
977 }
978
979 pReq->state = MV_CESA_PENDING;
980
981 pCesaReqEmpty = MV_CESA_REQ_NEXT_PTR(pReq);
982 cesaReqResources -= 1;
983
984 /* #ifdef CESA_DEBUG */
985 if( (cesaQueueDepth - cesaReqResources) > cesaStats.maxReqCount)
986 cesaStats.maxReqCount = (cesaQueueDepth - cesaReqResources);
987 /* #endif CESA_DEBUG */
988
989 cesaLastSid = sid;
990
991 #if (MV_CESA_VERSION >= 3)
992 /* Are we within chain bounderies and follows the first request ? */
993 if((chainReqNum > 0) && (chainReqNum < MAX_CESA_CHAIN_LENGTH)) {
994 if(chainIndex) {
995 pFromReq = MV_CESA_REQ_PREV_PTR(pReq);
996 pToReq = pReq;
997 pReq->state = MV_CESA_CHAIN;
998 /* assume concatenating is possible */
999 pFromReq->dma[pFromReq->frags.numFrag-1].pDmaLast->phyNextDescPtr =
1000 MV_32BIT_LE(mvCesaVirtToPhys(&pToReq->dmaDescBuf, pToReq->dma[0].pDmaFirst));
1001 mvOsCacheFlush(NULL, pFromReq->dma[pFromReq->frags.numFrag-1].pDmaLast, sizeof(MV_DMA_DESC));
1002
1003 /* align active & next pointers */
1004 if(pNextActiveChain->state != MV_CESA_PENDING)
1005 pEndCurrChain = pNextActiveChain = MV_CESA_REQ_NEXT_PTR(pReq);
1006 }
1007 else { /* we have only one chain, start new one */
1008 chainReqNum = 0;
1009 chainIndex++;
1010 /* align active & next pointers */
1011 if(pNextActiveChain->state != MV_CESA_PENDING)
1012 pEndCurrChain = pNextActiveChain = pReq;
1013 }
1014 }
1015 else {
1016 /* In case we concatenate full chain */
1017 if(chainReqNum == MAX_CESA_CHAIN_LENGTH) {
1018 chainIndex++;
1019 if(pNextActiveChain->state != MV_CESA_PENDING)
1020 pEndCurrChain = pNextActiveChain = pReq;
1021 chainReqNum = 0;
1022 }
1023
1024 pReq = pCesaReqProcess;
1025 if(pReq->state == MV_CESA_PENDING) {
1026 pNextActiveChain = pReq;
1027 pEndCurrChain = MV_CESA_REQ_NEXT_PTR(pReq);
1028 /* Start Process new request */
1029 mvCesaReqProcessStart(pReq);
1030 }
1031 }
1032
1033 chainReqNum++;
1034
1035 if((chainIndex < MAX_CESA_CHAIN_LENGTH) && (chainReqNum > cesaStats.maxChainUsage))
1036 cesaStats.maxChainUsage = chainReqNum;
1037
1038 #else
1039
1040 /* Check status of CESA channels and process requests if possible */
1041 pReq = pCesaReqProcess;
1042 if(pReq->state == MV_CESA_PENDING)
1043 {
1044 /* Start Process new request */
1045 mvCesaReqProcessStart(pReq);
1046 }
1047 #endif
1048 /* If request queue became FULL - return MV_NO_MORE */
1049 if(cesaReqResources == 0)
1050 return MV_NO_MORE;
1051
1052 return MV_OK;
1053
1054 }
1055
1056 /*******************************************************************************
1057 * mvCesaReadyGet - Get crypto request that processing is finished
1058 *
1059 * DESCRIPTION:
1060 * This function complete request processing and return ready request to
1061 * caller. To don't miss interrupts the caller must call this function
1062 * while MV_OK or MV_TERMINATE values returned.
1063 *
1064 * INPUT:
1065 * MV_U32 chanMap - map of CESA channels finished thier job
1066 * accordingly with CESA Cause register.
1067 * MV_CESA_RESULT* pResult - pointer to structure contains information
1068 * about ready request. It includes pointer to
1069 * user private structure "pReqPrv", session identifier
1070 * for this request "sessionId" and return code.
1071 * Return code set to MV_FAIL if calculated digest value
1072 * on decode direction is different than digest value
1073 * in the packet.
1074 *
1075 * RETURN:
1076 * MV_OK - Success, ready request is returned.
1077 * MV_NOT_READY - Next request is not ready yet. New interrupt will
1078 * be generated for futher request processing.
1079 * MV_EMPTY - There is no more request for processing.
1080 * MV_BUSY - Fragmented request is not ready yet.
1081 * MV_TERMINATE - Call this function once more to complete processing
1082 * of fragmented request.
1083 *
1084 *******************************************************************************/
1085 MV_STATUS mvCesaReadyGet(MV_CESA_RESULT* pResult)
1086 {
1087 MV_STATUS status, readyStatus = MV_NOT_READY;
1088 MV_U32 statusReg;
1089 MV_CESA_REQ* pReq;
1090 MV_CESA_SA* pSA;
1091
1092 #if (MV_CESA_VERSION >= 3)
1093 if(isFirstReq == MV_TRUE) {
1094 if(chainIndex == 0)
1095 chainReqNum = 0;
1096
1097 isFirstReq = MV_FALSE;
1098
1099 if(pNextActiveChain->state == MV_CESA_PENDING) {
1100 /* Start request Process */
1101 mvCesaReqProcessStart(pNextActiveChain);
1102 pEndCurrChain = pNextActiveChain;
1103 if(chainIndex > 0)
1104 chainIndex--;
1105 /* Update pNextActiveChain to next chain head */
1106 while(pNextActiveChain->state == MV_CESA_CHAIN)
1107 pNextActiveChain = MV_CESA_REQ_NEXT_PTR(pNextActiveChain);
1108 }
1109 }
1110
1111 /* Check if there are more processed requests - can we remove pEndCurrChain ??? */
1112 if(pCesaReqProcess == pEndCurrChain) {
1113 isFirstReq = MV_TRUE;
1114 pEndCurrChain = pNextActiveChain;
1115 #else
1116 if(pCesaReqProcess->state != MV_CESA_PROCESS) {
1117 #endif
1118 return MV_EMPTY;
1119 }
1120
1121 #ifdef CESA_DEBUG
1122 statusReg = MV_REG_READ(MV_CESA_STATUS_REG);
1123 if( statusReg & MV_CESA_STATUS_ACTIVE_MASK )
1124 {
1125 mvOsPrintf("mvCesaReadyGet: Not Ready, Status = 0x%x\n", statusReg);
1126 cesaStats.notReadyCount++;
1127 return MV_NOT_READY;
1128 }
1129 #endif /* CESA_DEBUG */
1130
1131 cesaStats.readyCount++;
1132
1133 pReq = pCesaReqProcess;
1134 pSA = &pCesaSAD[pReq->pCmd->sessionId];
1135
1136 pResult->retCode = MV_OK;
1137 if(pReq->fragMode != MV_CESA_FRAG_NONE)
1138 {
1139 MV_U8* pNewDigest;
1140 int frag;
1141 #if (MV_CESA_VERSION >= 3)
1142 pReq->frags.nextFrag = 1;
1143 while(pReq->frags.nextFrag <= pReq->frags.numFrag) {
1144 #endif
1145 frag = (pReq->frags.nextFrag - 1);
1146
1147 /* Restore DMA descriptor list */
1148 pReq->dma[frag].pDmaLast->phyNextDescPtr =
1149 MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[frag].pDmaLast[1]));
1150 pReq->dma[frag].pDmaLast = NULL;
1151
1152 /* Special processing for finished fragmented request */
1153 if(pReq->frags.nextFrag >= pReq->frags.numFrag)
1154 {
1155 mvCesaMbufCacheUnmap(pReq->pCmd->pDst, 0, pReq->pCmd->pDst->mbufSize);
1156
1157 /* Fragmented packet is ready */
1158 if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1159 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
1160 {
1161 int macDataSize = pReq->pCmd->macLength - pReq->frags.macSize;
1162
1163 if(macDataSize != 0)
1164 {
1165 /* Calculate all other blocks by SW */
1166 mvCesaFragAuthComplete(pReq, pSA, macDataSize);
1167 }
1168
1169 /* Copy new digest from SRAM to the Destination buffer */
1170 pNewDigest = cesaSramVirtPtr->buf + pReq->frags.newDigestOffset;
1171 status = mvCesaCopyToMbuf(pNewDigest, pReq->pCmd->pDst,
1172 pReq->pCmd->digestOffset, pSA->digestSize);
1173
1174 /* For decryption: Compare new digest value with original one */
1175 if((pSA->config & MV_CESA_DIRECTION_MASK) ==
1176 (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
1177 {
1178 if( memcmp(pNewDigest, pReq->frags.orgDigest, pSA->digestSize) != 0)
1179 {
1180 /*
1181 mvOsPrintf("Digest error: chan=%d, newDigest=%p, orgDigest=%p, status = 0x%x\n",
1182 chan, pNewDigest, pReq->frags.orgDigest, MV_REG_READ(MV_CESA_STATUS_REG));
1183 */
1184 /* Signiture verification is failed */
1185 pResult->retCode = MV_FAIL;
1186 }
1187 }
1188 }
1189 readyStatus = MV_OK;
1190 }
1191 #if (MV_CESA_VERSION >= 3)
1192 pReq->frags.nextFrag++;
1193 }
1194 #endif
1195 }
1196 else
1197 {
1198 mvCesaMbufCacheUnmap(pReq->pCmd->pDst, 0, pReq->pCmd->pDst->mbufSize);
1199
1200 /* Restore DMA descriptor list */
1201 pReq->dma[0].pDmaLast->phyNextDescPtr =
1202 MV_32BIT_LE(mvCesaVirtToPhys(&pReq->dmaDescBuf, &pReq->dma[0].pDmaLast[1]));
1203 pReq->dma[0].pDmaLast = NULL;
1204 if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
1205 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) ) &&
1206 ((pSA->config & MV_CESA_DIRECTION_MASK) ==
1207 (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT)) )
1208 {
1209 /* For AUTH on decode : Check Digest result in Status register */
1210 statusReg = MV_REG_READ(MV_CESA_STATUS_REG);
1211 if(statusReg & MV_CESA_STATUS_DIGEST_ERR_MASK)
1212 {
1213 /*
1214 mvOsPrintf("Digest error: chan=%d, status = 0x%x\n",
1215 chan, statusReg);
1216 */
1217 /* Signiture verification is failed */
1218 pResult->retCode = MV_FAIL;
1219 }
1220 }
1221 readyStatus = MV_OK;
1222 }
1223
1224 if(readyStatus == MV_OK)
1225 {
1226 /* If Request is ready - Prepare pResult structure */
1227 pResult->pReqPrv = pReq->pCmd->pReqPrv;
1228 pResult->sessionId = pReq->pCmd->sessionId;
1229
1230 pReq->state = MV_CESA_IDLE;
1231 pCesaReqProcess = MV_CESA_REQ_NEXT_PTR(pReq);
1232 cesaReqResources++;
1233
1234 if(pSA->ctrMode)
1235 {
1236 /* For AES CTR mode - complete processing and free allocated resources */
1237 mvCesaCtrModeComplete(pReq->pOrgCmd, pReq->pCmd);
1238 mvCesaCtrModeFinish(pReq->pCmd);
1239 pReq->pOrgCmd = NULL;
1240 }
1241 }
1242
1243 #if (MV_CESA_VERSION < 3)
1244 if(pCesaReqProcess->state == MV_CESA_PROCESS)
1245 {
1246 /* Start request Process */
1247 mvCesaReqProcessStart(pCesaReqProcess);
1248 if(readyStatus == MV_NOT_READY)
1249 readyStatus = MV_BUSY;
1250 }
1251 else if(pCesaReqProcess != pCesaReqEmpty)
1252 {
1253 /* Start process new request from the queue */
1254 mvCesaReqProcessStart(pCesaReqProcess);
1255 }
1256 #endif
1257 return readyStatus;
1258 }
1259
1260 /***************** Functions to work with CESA_MBUF structure ******************/
1261
1262 /*******************************************************************************
1263 * mvCesaMbufOffset - Locate offset in the Mbuf structure
1264 *
1265 * DESCRIPTION:
1266 * This function locates offset inside Multi-Bufeer structure.
1267 * It get fragment number and place in the fragment where the offset
1268 * is located.
1269 *
1270 *
1271 * INPUT:
1272 * MV_CESA_MBUF* pMbuf - Pointer to multi-buffer structure
1273 * int offset - Offset from the beginning of the data presented by
1274 * the Mbuf structure.
1275 *
1276 * OUTPUT:
1277 * int* pBufOffset - Offset from the beginning of the fragment where
1278 * the offset is located.
1279 *
1280 * RETURN:
1281 * int - Number of fragment, where the offset is located\
1282 *
1283 *******************************************************************************/
1284 int mvCesaMbufOffset(MV_CESA_MBUF* pMbuf, int offset, int* pBufOffset)
1285 {
1286 int frag = 0;
1287
1288 while(offset > 0)
1289 {
1290 if(frag >= pMbuf->numFrags)
1291 {
1292 mvOsPrintf("mvCesaMbufOffset: Error: frag (%d) > numFrags (%d)\n",
1293 frag, pMbuf->numFrags);
1294 return MV_INVALID;
1295 }
1296 if(offset < pMbuf->pFrags[frag].bufSize)
1297 {
1298 break;
1299 }
1300 offset -= pMbuf->pFrags[frag].bufSize;
1301 frag++;
1302 }
1303 if(pBufOffset != NULL)
1304 *pBufOffset = offset;
1305
1306 return frag;
1307 }
1308
1309 /*******************************************************************************
1310 * mvCesaCopyFromMbuf - Copy data from the Mbuf structure to continuous buffer
1311 *
1312 * DESCRIPTION:
1313 *
1314 *
1315 * INPUT:
1316 * MV_U8* pDstBuf - Pointer to continuous buffer, where data is
1317 * copied to.
1318 * MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is
1319 * copied from.
1320 * int offset - Offset in the Mbuf structure where located first
1321 * byte of data should be copied.
1322 * int size - Size of data should be copied
1323 *
1324 * RETURN:
1325 * MV_OK - Success, all data is copied successfully.
1326 * MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range.
1327 * No data is copied.
1328 * MV_EMPTY - Multi-buffer structure has not enough data to copy
1329 * Data from the offset to end of Mbuf data is copied.
1330 *
1331 *******************************************************************************/
1332 MV_STATUS mvCesaCopyFromMbuf(MV_U8* pDstBuf, MV_CESA_MBUF* pSrcMbuf,
1333 int offset, int size)
1334 {
1335 int frag, fragOffset, bufSize;
1336 MV_U8* pBuf;
1337
1338 if(size == 0)
1339 return MV_OK;
1340
1341 frag = mvCesaMbufOffset(pSrcMbuf, offset, &fragOffset);
1342 if(frag == MV_INVALID)
1343 {
1344 mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
1345 return MV_OUT_OF_RANGE;
1346 }
1347
1348 bufSize = pSrcMbuf->pFrags[frag].bufSize - fragOffset;
1349 pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr + fragOffset;
1350 while(MV_TRUE)
1351 {
1352 if(size <= bufSize)
1353 {
1354 memcpy(pDstBuf, pBuf, size);
1355 return MV_OK;
1356 }
1357 memcpy(pDstBuf, pBuf, bufSize);
1358 size -= bufSize;
1359 frag++;
1360 pDstBuf += bufSize;
1361 if(frag >= pSrcMbuf->numFrags)
1362 break;
1363
1364 bufSize = pSrcMbuf->pFrags[frag].bufSize;
1365 pBuf = pSrcMbuf->pFrags[frag].bufVirtPtr;
1366 }
1367 mvOsPrintf("mvCesaCopyFromMbuf: Mbuf is EMPTY - %d bytes isn't copied\n",
1368 size);
1369 return MV_EMPTY;
1370 }
1371
1372 /*******************************************************************************
1373 * mvCesaCopyToMbuf - Copy data from continuous buffer to the Mbuf structure
1374 *
1375 * DESCRIPTION:
1376 *
1377 *
1378 * INPUT:
1379 * MV_U8* pSrcBuf - Pointer to continuous buffer, where data is
1380 * copied from.
1381 * MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is
1382 * copied to.
1383 * int offset - Offset in the Mbuf structure where located first
1384 * byte of data should be copied.
1385 * int size - Size of data should be copied
1386 *
1387 * RETURN:
1388 * MV_OK - Success, all data is copied successfully.
1389 * MV_OUT_OF_RANGE - Failed, offset is out of Multi-buffer data range.
1390 * No data is copied.
1391 * MV_FULL - Multi-buffer structure has not enough place to copy
1392 * all data. Data from the offset to end of Mbuf data
1393 * is copied.
1394 *
1395 *******************************************************************************/
1396 MV_STATUS mvCesaCopyToMbuf(MV_U8* pSrcBuf, MV_CESA_MBUF* pDstMbuf,
1397 int offset, int size)
1398 {
1399 int frag, fragOffset, bufSize;
1400 MV_U8* pBuf;
1401
1402 if(size == 0)
1403 return MV_OK;
1404
1405 frag = mvCesaMbufOffset(pDstMbuf, offset, &fragOffset);
1406 if(frag == MV_INVALID)
1407 {
1408 mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
1409 return MV_OUT_OF_RANGE;
1410 }
1411
1412 bufSize = pDstMbuf->pFrags[frag].bufSize - fragOffset;
1413 pBuf = pDstMbuf->pFrags[frag].bufVirtPtr + fragOffset;
1414 while(MV_TRUE)
1415 {
1416 if(size <= bufSize)
1417 {
1418 memcpy(pBuf, pSrcBuf, size);
1419 return MV_OK;
1420 }
1421 memcpy(pBuf, pSrcBuf, bufSize);
1422 size -= bufSize;
1423 frag++;
1424 pSrcBuf += bufSize;
1425 if(frag >= pDstMbuf->numFrags)
1426 break;
1427
1428 bufSize = pDstMbuf->pFrags[frag].bufSize;
1429 pBuf = pDstMbuf->pFrags[frag].bufVirtPtr;
1430 }
1431 mvOsPrintf("mvCesaCopyToMbuf: Mbuf is FULL - %d bytes isn't copied\n",
1432 size);
1433 return MV_FULL;
1434 }
1435
1436 /*******************************************************************************
1437 * mvCesaMbufCopy - Copy data from one Mbuf structure to the other Mbuf structure
1438 *
1439 * DESCRIPTION:
1440 *
1441 *
1442 * INPUT:
1443 *
1444 * MV_CESA_MBUF* pDstMbuf - Pointer to multi-buffer structure where data is
1445 * copied to.
1446 * int dstMbufOffset - Offset in the dstMbuf structure where first byte
1447 * of data should be copied to.
1448 * MV_CESA_MBUF* pSrcMbuf - Pointer to multi-buffer structure where data is
1449 * copied from.
1450 * int srcMbufOffset - Offset in the srcMbuf structure where first byte
1451 * of data should be copied from.
1452 * int size - Size of data should be copied
1453 *
1454 * RETURN:
1455 * MV_OK - Success, all data is copied successfully.
1456 * MV_OUT_OF_RANGE - Failed, srcMbufOffset or dstMbufOffset is out of
1457 * srcMbuf or dstMbuf structure correspondently.
1458 * No data is copied.
1459 * MV_BAD_SIZE - srcMbuf or dstMbuf structure is too small to copy
1460 * all data. Partial data is copied
1461 *
1462 *******************************************************************************/
1463 MV_STATUS mvCesaMbufCopy(MV_CESA_MBUF* pMbufDst, int dstMbufOffset,
1464 MV_CESA_MBUF* pMbufSrc, int srcMbufOffset, int size)
1465 {
1466 int srcFrag, dstFrag, srcSize, dstSize, srcOffset, dstOffset;
1467 int copySize;
1468 MV_U8 *pSrc, *pDst;
1469
1470 if(size == 0)
1471 return MV_OK;
1472
1473 srcFrag = mvCesaMbufOffset(pMbufSrc, srcMbufOffset, &srcOffset);
1474 if(srcFrag == MV_INVALID)
1475 {
1476 mvOsPrintf("CESA srcMbuf Error: offset (%d) out of range\n", srcMbufOffset);
1477 return MV_OUT_OF_RANGE;
1478 }
1479 pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr + srcOffset;
1480 srcSize = pMbufSrc->pFrags[srcFrag].bufSize - srcOffset;
1481
1482 dstFrag = mvCesaMbufOffset(pMbufDst, dstMbufOffset, &dstOffset);
1483 if(dstFrag == MV_INVALID)
1484 {
1485 mvOsPrintf("CESA dstMbuf Error: offset (%d) out of range\n", dstMbufOffset);
1486 return MV_OUT_OF_RANGE;
1487 }
1488 pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr + dstOffset;
1489 dstSize = pMbufDst->pFrags[dstFrag].bufSize - dstOffset;
1490
1491 while(size > 0)
1492 {
1493 copySize = MV_MIN(srcSize, dstSize);
1494 if(size <= copySize)
1495 {
1496 memcpy(pDst, pSrc, size);
1497 return MV_OK;
1498 }
1499 memcpy(pDst, pSrc, copySize);
1500 size -= copySize;
1501 srcSize -= copySize;
1502 dstSize -= copySize;
1503
1504 if(srcSize == 0)
1505 {
1506 srcFrag++;
1507 if(srcFrag >= pMbufSrc->numFrags)
1508 break;
1509
1510 pSrc = pMbufSrc->pFrags[srcFrag].bufVirtPtr;
1511 srcSize = pMbufSrc->pFrags[srcFrag].bufSize;
1512 }
1513
1514 if(dstSize == 0)
1515 {
1516 dstFrag++;
1517 if(dstFrag >= pMbufDst->numFrags)
1518 break;
1519
1520 pDst = pMbufDst->pFrags[dstFrag].bufVirtPtr;
1521 dstSize = pMbufDst->pFrags[dstFrag].bufSize;
1522 }
1523 }
1524 mvOsPrintf("mvCesaMbufCopy: BAD size - %d bytes isn't copied\n",
1525 size);
1526
1527 return MV_BAD_SIZE;
1528 }
1529
1530 static MV_STATUS mvCesaMbufCacheUnmap(MV_CESA_MBUF* pMbuf, int offset, int size)
1531 {
1532 int frag, fragOffset, bufSize;
1533 MV_U8* pBuf;
1534
1535 if(size == 0)
1536 return MV_OK;
1537
1538 frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
1539 if(frag == MV_INVALID)
1540 {
1541 mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
1542 return MV_OUT_OF_RANGE;
1543 }
1544
1545 bufSize = pMbuf->pFrags[frag].bufSize - fragOffset;
1546 pBuf = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
1547 while(MV_TRUE)
1548 {
1549 if(size <= bufSize)
1550 {
1551 mvOsCacheUnmap(NULL, mvOsIoVirtToPhy(NULL, pBuf), size);
1552 return MV_OK;
1553 }
1554
1555 mvOsCacheUnmap(NULL, mvOsIoVirtToPhy(NULL, pBuf), bufSize);
1556 size -= bufSize;
1557 frag++;
1558 if(frag >= pMbuf->numFrags)
1559 break;
1560
1561 bufSize = pMbuf->pFrags[frag].bufSize;
1562 pBuf = pMbuf->pFrags[frag].bufVirtPtr;
1563 }
1564 mvOsPrintf("%s: Mbuf is FULL - %d bytes isn't Unmapped\n",
1565 __FUNCTION__, size);
1566 return MV_FULL;
1567 }
1568
1569
1570 /*************************************** Local Functions ******************************/
1571
1572 /*******************************************************************************
1573 * mvCesaFragReqProcess - Process fragmented request
1574 *
1575 * DESCRIPTION:
1576 * This function processes a fragment of fragmented request (First, Middle or Last)
1577 *
1578 *
1579 * INPUT:
1580 * MV_CESA_REQ* pReq - Pointer to the request in the request queue.
1581 *
1582 * RETURN:
1583 * MV_OK - The fragment is successfully passed to HW for processing.
1584 * MV_TERMINATE - Means, that HW finished its work on this packet and no more
1585 * interrupts will be generated for this request.
1586 * Function mvCesaReadyGet() must be called to complete request
1587 * processing and get request result.
1588 *
1589 *******************************************************************************/
1590 static MV_STATUS mvCesaFragReqProcess(MV_CESA_REQ* pReq, MV_U8 frag)
1591 {
1592 int i, copySize, cryptoDataSize, macDataSize, sid;
1593 int cryptoIvOffset, digestOffset;
1594 MV_U32 config;
1595 MV_CESA_COMMAND* pCmd = pReq->pCmd;
1596 MV_CESA_SA* pSA;
1597 MV_CESA_MBUF* pMbuf;
1598 MV_DMA_DESC* pDmaDesc = pReq->dma[frag].pDmaFirst;
1599 MV_U8* pSramBuf = cesaSramVirtPtr->buf;
1600 int macTotalLen = 0;
1601 int fixOffset, cryptoOffset, macOffset;
1602
1603 cesaStats.fragCount++;
1604
1605 sid = pReq->pCmd->sessionId;
1606
1607 pSA = &pCesaSAD[sid];
1608
1609 cryptoIvOffset = digestOffset = 0;
1610 i = macDataSize = 0;
1611 cryptoDataSize = 0;
1612
1613 /* First fragment processing */
1614 if(pReq->fragMode == MV_CESA_FRAG_FIRST)
1615 {
1616 /* pReq->frags monitors processing of fragmented request between fragments */
1617 pReq->frags.bufOffset = 0;
1618 pReq->frags.cryptoSize = 0;
1619 pReq->frags.macSize = 0;
1620
1621 config = pSA->config | (MV_CESA_FRAG_FIRST << MV_CESA_FRAG_MODE_OFFSET);
1622
1623 /* fixOffset can be not equal to zero only for FIRST fragment */
1624 fixOffset = pReq->fixOffset;
1625 /* For FIRST fragment crypto and mac offsets are taken from pCmd */
1626 cryptoOffset = pCmd->cryptoOffset;
1627 macOffset = pCmd->macOffset;
1628
1629 copySize = sizeof(cesaSramVirtPtr->buf) - pReq->fixOffset;
1630
1631 /* Find fragment size: Must meet all requirements for CRYPTO and MAC
1632 * cryptoDataSize - size of data will be encrypted/decrypted in this fragment
1633 * macDataSize - size of data will be signed/verified in this fragment
1634 * copySize - size of data will be copied from srcMbuf to SRAM and
1635 * back to dstMbuf for this fragment
1636 */
1637 mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset,
1638 &copySize, &cryptoDataSize, &macDataSize);
1639
1640 if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1641 (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET))
1642 {
1643 /* CryptoIV special processing */
1644 if( (pSA->config & MV_CESA_CRYPTO_MODE_MASK) ==
1645 (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT) )
1646 {
1647 /* In CBC mode for encode direction when IV from user */
1648 if( (pCmd->ivFromUser) &&
1649 ((pSA->config & MV_CESA_DIRECTION_MASK) ==
1650 (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) )
1651 {
1652
1653 /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer,
1654 * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place
1655 * in the buffer to SRAM IVPointer
1656 */
1657 i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
1658 MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
1659 }
1660
1661 /* Special processing when IV is not located in the first fragment */
1662 if(pCmd->ivOffset > (copySize - pSA->cryptoIvSize))
1663 {
1664 /* Prepare dummy place for cryptoIV in SRAM */
1665 cryptoIvOffset = cesaSramVirtPtr->tempCryptoIV - mvCesaSramAddrGet();
1666
1667 /* For Decryption: Copy IV value from pCmd->ivOffset to Special SRAM place */
1668 if((pSA->config & MV_CESA_DIRECTION_MASK) ==
1669 (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
1670 {
1671 i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->tempCryptoIV, &pDmaDesc[i],
1672 MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
1673 }
1674 else
1675 {
1676 /* For Encryption when IV is NOT from User: */
1677 /* Copy IV from SRAM to buffer (pCmd->ivOffset) */
1678 if(pCmd->ivFromUser == 0)
1679 {
1680 /* copy IV value from cryptoIV to Buffer (pCmd->ivOffset) */
1681 i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
1682 MV_TRUE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
1683 }
1684 }
1685 }
1686 else
1687 {
1688 cryptoIvOffset = pCmd->ivOffset;
1689 }
1690 }
1691 }
1692
1693 if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1694 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
1695 {
1696 /* MAC digest special processing on Decode direction */
1697 if((pSA->config & MV_CESA_DIRECTION_MASK) ==
1698 (MV_CESA_DIR_DECODE << MV_CESA_DIRECTION_BIT))
1699 {
1700 /* Save digest from pCmd->digestOffset */
1701 mvCesaCopyFromMbuf(pReq->frags.orgDigest,
1702 pCmd->pSrc, pCmd->digestOffset, pSA->digestSize);
1703
1704 /* If pCmd->digestOffset is not located on the first */
1705 if(pCmd->digestOffset > (copySize - pSA->digestSize))
1706 {
1707 MV_U8 digestZero[MV_CESA_MAX_DIGEST_SIZE];
1708
1709 /* Set zeros to pCmd->digestOffset (DRAM) */
1710 memset(digestZero, 0, MV_CESA_MAX_DIGEST_SIZE);
1711 mvCesaCopyToMbuf(digestZero, pCmd->pSrc, pCmd->digestOffset, pSA->digestSize);
1712
1713 /* Prepare dummy place for digest in SRAM */
1714 digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
1715 }
1716 else
1717 {
1718 digestOffset = pCmd->digestOffset;
1719 }
1720 }
1721 }
1722 /* Update SA in SRAM */
1723 if(cesaLastSid != sid)
1724 {
1725 mvCesaSramSaUpdate(sid, &pDmaDesc[i]);
1726 i++;
1727 }
1728
1729 pReq->fragMode = MV_CESA_FRAG_MIDDLE;
1730 }
1731 else
1732 {
1733 /* Continue fragment */
1734 fixOffset = 0;
1735 cryptoOffset = 0;
1736 macOffset = 0;
1737 if( (pCmd->pSrc->mbufSize - pReq->frags.bufOffset) <= sizeof(cesaSramVirtPtr->buf))
1738 {
1739 /* Last fragment */
1740 config = pSA->config | (MV_CESA_FRAG_LAST << MV_CESA_FRAG_MODE_OFFSET);
1741 pReq->fragMode = MV_CESA_FRAG_LAST;
1742 copySize = pCmd->pSrc->mbufSize - pReq->frags.bufOffset;
1743
1744 if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1745 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
1746 {
1747 macDataSize = pCmd->macLength - pReq->frags.macSize;
1748
1749 /* If pCmd->digestOffset is not located on last fragment */
1750 if(pCmd->digestOffset < pReq->frags.bufOffset)
1751 {
1752 /* Prepare dummy place for digest in SRAM */
1753 digestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
1754 }
1755 else
1756 {
1757 digestOffset = pCmd->digestOffset - pReq->frags.bufOffset;
1758 }
1759 pReq->frags.newDigestOffset = digestOffset;
1760 macTotalLen = pCmd->macLength;
1761
1762 /* HW can't calculate the Digest correctly for fragmented packets
1763 * in the following cases:
1764 * - MV88F5182 ||
1765 * - MV88F5181L when total macLength more that 16 Kbytes ||
1766 * - total macLength more that 64 Kbytes
1767 */
1768 if( (mvCtrlModelGet() == MV_5182_DEV_ID) ||
1769 ( (mvCtrlModelGet() == MV_5181_DEV_ID) &&
1770 (mvCtrlRevGet() >= MV_5181L_A0_REV) &&
1771 (pCmd->macLength >= (1 << 14)) ) )
1772 {
1773 return MV_TERMINATE;
1774 }
1775 }
1776 if( (pSA->config & MV_CESA_OPERATION_MASK) !=
1777 (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
1778 {
1779 cryptoDataSize = pCmd->cryptoLength - pReq->frags.cryptoSize;
1780 }
1781
1782 /* cryptoIvOffset - don't care */
1783 }
1784 else
1785 {
1786 /* WA for MV88F5182 SHA1 and MD5 fragmentation mode */
1787 if( (mvCtrlModelGet() == MV_5182_DEV_ID) &&
1788 (((pSA->config & MV_CESA_MAC_MODE_MASK) ==
1789 (MV_CESA_MAC_MD5 << MV_CESA_MAC_MODE_OFFSET)) ||
1790 ((pSA->config & MV_CESA_MAC_MODE_MASK) ==
1791 (MV_CESA_MAC_SHA1 << MV_CESA_MAC_MODE_OFFSET))) )
1792 {
1793 pReq->frags.newDigestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
1794 pReq->fragMode = MV_CESA_FRAG_LAST;
1795
1796 return MV_TERMINATE;
1797 }
1798 /* Middle fragment */
1799 config = pSA->config | (MV_CESA_FRAG_MIDDLE << MV_CESA_FRAG_MODE_OFFSET);
1800 copySize = sizeof(cesaSramVirtPtr->buf);
1801 /* digestOffset and cryptoIvOffset - don't care */
1802
1803 /* Find fragment size */
1804 mvCesaFragSizeFind(pSA, pReq, cryptoOffset, macOffset,
1805 &copySize, &cryptoDataSize, &macDataSize);
1806 }
1807 }
1808 /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
1809 pMbuf = pCmd->pSrc;
1810 i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
1811 MV_FALSE, pReq->frags.bufOffset, copySize, pCmd->skipFlush);
1812
1813 /* Prepare CESA descriptor to copy from DRAM to SRAM by DMA */
1814 mvCesaSramDescrBuild(config, frag,
1815 cryptoOffset + fixOffset, cryptoIvOffset + fixOffset,
1816 cryptoDataSize, macOffset + fixOffset,
1817 digestOffset + fixOffset, macDataSize, macTotalLen,
1818 pReq, &pDmaDesc[i]);
1819 i++;
1820
1821 /* Add special descriptor Ownership for CPU */
1822 pDmaDesc[i].byteCnt = 0;
1823 pDmaDesc[i].phySrcAdd = 0;
1824 pDmaDesc[i].phyDestAdd = 0;
1825 i++;
1826
1827 /********* Prepare DMA descriptors to copy from SRAM to pDst *********/
1828 pMbuf = pCmd->pDst;
1829 i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
1830 MV_TRUE, pReq->frags.bufOffset, copySize, pCmd->skipFlush);
1831
1832 /* Next field of Last DMA descriptor must be NULL */
1833 pDmaDesc[i-1].phyNextDescPtr = 0;
1834 pReq->dma[frag].pDmaLast = &pDmaDesc[i-1];
1835 mvOsCacheFlush(NULL, pReq->dma[frag].pDmaFirst,
1836 i*sizeof(MV_DMA_DESC));
1837
1838 /*mvCesaDebugDescriptor(&cesaSramVirtPtr->desc[frag]);*/
1839
1840 pReq->frags.bufOffset += copySize;
1841 pReq->frags.cryptoSize += cryptoDataSize;
1842 pReq->frags.macSize += macDataSize;
1843
1844 return MV_OK;
1845 }
1846
1847
1848 /*******************************************************************************
1849 * mvCesaReqProcess - Process regular (Non-fragmented) request
1850 *
1851 * DESCRIPTION:
1852 * This function processes the whole (not fragmented) request
1853 *
1854 * INPUT:
1855 * MV_CESA_REQ* pReq - Pointer to the request in the request queue.
1856 *
1857 * RETURN:
1858 * MV_OK - The request is successfully passed to HW for processing.
1859 * Other - Failure. The request will not be processed
1860 *
1861 *******************************************************************************/
1862 static MV_STATUS mvCesaReqProcess(MV_CESA_REQ* pReq)
1863 {
1864 MV_CESA_MBUF *pMbuf;
1865 MV_DMA_DESC *pDmaDesc;
1866 MV_U8 *pSramBuf;
1867 int sid, i, fixOffset;
1868 MV_CESA_SA *pSA;
1869 MV_CESA_COMMAND *pCmd = pReq->pCmd;
1870
1871 cesaStats.procCount++;
1872
1873 sid = pCmd->sessionId;
1874 pSA = &pCesaSAD[sid];
1875 pDmaDesc = pReq->dma[0].pDmaFirst;
1876 pSramBuf = cesaSramVirtPtr->buf;
1877 fixOffset = pReq->fixOffset;
1878
1879 /*
1880 mvOsPrintf("mvCesaReqProcess: sid=%d, pSA=%p, pDmaDesc=%p, pSramBuf=%p\n",
1881 sid, pSA, pDmaDesc, pSramBuf);
1882 */
1883 i = 0;
1884
1885 /* Crypto IV Special processing in CBC mode for Encryption direction */
1886 if( ((pSA->config & MV_CESA_OPERATION_MASK) != (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) &&
1887 ((pSA->config & MV_CESA_CRYPTO_MODE_MASK) == (MV_CESA_CRYPTO_CBC << MV_CESA_CRYPTO_MODE_BIT)) &&
1888 ((pSA->config & MV_CESA_DIRECTION_MASK) == (MV_CESA_DIR_ENCODE << MV_CESA_DIRECTION_BIT)) &&
1889 (pCmd->ivFromUser) )
1890 {
1891 /* For Crypto Encode in CBC mode HW always takes IV from SRAM IVPointer,
1892 * (not from IVBufPointer). So when ivFromUser==1, we should copy IV from user place
1893 * in the buffer to SRAM IVPointer
1894 */
1895 i += mvCesaDmaCopyPrepare(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
1896 MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
1897 }
1898
1899 /* Update SA in SRAM */
1900 if(cesaLastSid != sid)
1901 {
1902 mvCesaSramSaUpdate(sid, &pDmaDesc[i]);
1903 i++;
1904 }
1905
1906 /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
1907 pMbuf = pCmd->pSrc;
1908 i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
1909 MV_FALSE, 0, pMbuf->mbufSize, pCmd->skipFlush);
1910
1911 /* Prepare Security Accelerator descriptor to SRAM words 0 - 7 */
1912 mvCesaSramDescrBuild(pSA->config, 0, pCmd->cryptoOffset + fixOffset,
1913 pCmd->ivOffset + fixOffset, pCmd->cryptoLength,
1914 pCmd->macOffset + fixOffset, pCmd->digestOffset + fixOffset,
1915 pCmd->macLength, pCmd->macLength, pReq, &pDmaDesc[i]);
1916 i++;
1917
1918 /* Add special descriptor Ownership for CPU */
1919 pDmaDesc[i].byteCnt = 0;
1920 pDmaDesc[i].phySrcAdd = 0;
1921 pDmaDesc[i].phyDestAdd = 0;
1922 i++;
1923
1924 /********* Prepare DMA descriptors to copy from SRAM to pDst *********/
1925 pMbuf = pCmd->pDst;
1926 i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
1927 MV_TRUE, 0, pMbuf->mbufSize, pCmd->skipFlush);
1928
1929 /* Next field of Last DMA descriptor must be NULL */
1930 pDmaDesc[i-1].phyNextDescPtr = 0;
1931 pReq->dma[0].pDmaLast = &pDmaDesc[i-1];
1932 mvOsCacheFlush(NULL, pReq->dma[0].pDmaFirst, i*sizeof(MV_DMA_DESC));
1933
1934 return MV_OK;
1935 }
1936
1937
1938 /*******************************************************************************
1939 * mvCesaSramDescrBuild - Set CESA descriptor in SRAM
1940 *
1941 * DESCRIPTION:
1942 * This function builds CESA descriptor in SRAM from all Command parameters
1943 *
1944 *
1945 * INPUT:
1946 * int chan - CESA channel uses the descriptor
1947 * MV_U32 config - 32 bits of WORD_0 in CESA descriptor structure
1948 * int cryptoOffset - Offset from the beginning of SRAM buffer where
1949 * data for encryption/decription is started.
1950 * int ivOffset - Offset of crypto IV from the SRAM base. Valid only
1951 * for first fragment.
1952 * int cryptoLength - Size (in bytes) of data for encryption/descryption
1953 * operation on this fragment.
1954 * int macOffset - Offset from the beginning of SRAM buffer where
1955 * data for Authentication is started
1956 * int digestOffset - Offset from the beginning of SRAM buffer where
1957 * digest is located. Valid for first and last fragments.
1958 * int macLength - Size (in bytes) of data for Authentication
1959 * operation on this fragment.
1960 * int macTotalLen - Toatl size (in bytes) of data for Authentication
1961 * operation on the whole request (packet). Valid for
1962 * last fragment only.
1963 *
1964 * RETURN: None
1965 *
1966 *******************************************************************************/
1967 static void mvCesaSramDescrBuild(MV_U32 config, int frag,
1968 int cryptoOffset, int ivOffset, int cryptoLength,
1969 int macOffset, int digestOffset, int macLength,
1970 int macTotalLen, MV_CESA_REQ* pReq, MV_DMA_DESC* pDmaDesc)
1971 {
1972 MV_CESA_DESC* pCesaDesc = &pReq->pCesaDesc[frag];
1973 MV_CESA_DESC* pSramDesc = pSramDesc = &cesaSramVirtPtr->desc;
1974 MV_U16 sramBufOffset = (MV_U16)((MV_U8*)cesaSramVirtPtr->buf - mvCesaSramAddrGet());
1975
1976 pCesaDesc->config = MV_32BIT_LE(config);
1977
1978 if( (config & MV_CESA_OPERATION_MASK) !=
1979 (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
1980 {
1981 /* word 1 */
1982 pCesaDesc->cryptoSrcOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset);
1983 pCesaDesc->cryptoDstOffset = MV_16BIT_LE(sramBufOffset + cryptoOffset);
1984 /* word 2 */
1985 pCesaDesc->cryptoDataLen = MV_16BIT_LE(cryptoLength);
1986 /* word 3 */
1987 pCesaDesc->cryptoKeyOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.cryptoKey -
1988 mvCesaSramAddrGet()));
1989 /* word 4 */
1990 pCesaDesc->cryptoIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->cryptoIV -
1991 mvCesaSramAddrGet()));
1992 pCesaDesc->cryptoIvBufOffset = MV_16BIT_LE(sramBufOffset + ivOffset);
1993 }
1994
1995 if( (config & MV_CESA_OPERATION_MASK) !=
1996 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
1997 {
1998 /* word 5 */
1999 pCesaDesc->macSrcOffset = MV_16BIT_LE(sramBufOffset + macOffset);
2000 pCesaDesc->macTotalLen = MV_16BIT_LE(macTotalLen);
2001
2002 /* word 6 */
2003 pCesaDesc->macDigestOffset = MV_16BIT_LE(sramBufOffset + digestOffset);
2004 pCesaDesc->macDataLen = MV_16BIT_LE(macLength);
2005
2006 /* word 7 */
2007 pCesaDesc->macInnerIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macInnerIV -
2008 mvCesaSramAddrGet()));
2009 pCesaDesc->macOuterIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macOuterIV -
2010 mvCesaSramAddrGet()));
2011 }
2012 /* Prepare DMA descriptor to CESA descriptor from DRAM to SRAM */
2013 pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&pReq->cesaDescBuf, pCesaDesc));
2014 pDmaDesc->phyDestAdd = MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)pSramDesc));
2015 pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_DESC) | BIT31);
2016
2017 /* flush Source buffer */
2018 mvOsCacheFlush(NULL, pCesaDesc, sizeof(MV_CESA_DESC));
2019 }
2020
2021 /*******************************************************************************
2022 * mvCesaSramSaUpdate - Move required SA information to SRAM if needed.
2023 *
2024 * DESCRIPTION:
2025 * Copy to SRAM values of the required SA.
2026 *
2027 *
2028 * INPUT:
2029 * short sid - Session ID needs SRAM Cache update
2030 * MV_DMA_DESC *pDmaDesc - Pointer to DMA descriptor used to
2031 * copy SA values from DRAM to SRAM.
2032 *
2033 * RETURN:
2034 * MV_OK - Cache entry for this SA copied to SRAM.
2035 * MV_NO_CHANGE - Cache entry for this SA already exist in SRAM
2036 *
2037 *******************************************************************************/
2038 static INLINE void mvCesaSramSaUpdate(short sid, MV_DMA_DESC *pDmaDesc)
2039 {
2040 MV_CESA_SA *pSA = &pCesaSAD[sid];
2041
2042 /* Prepare DMA descriptor to Copy CACHE_SA from SA database in DRAM to SRAM */
2043 pDmaDesc->byteCnt = MV_32BIT_LE(sizeof(MV_CESA_SRAM_SA) | BIT31);
2044 pDmaDesc->phySrcAdd = MV_32BIT_LE(mvCesaVirtToPhys(&cesaSramSaBuf, pSA->pSramSA));
2045 pDmaDesc->phyDestAdd =
2046 MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)&cesaSramVirtPtr->sramSA));
2047
2048 /* Source buffer is already flushed during OpenSession*/
2049 /*mvOsCacheFlush(NULL, &pSA->sramSA, sizeof(MV_CESA_SRAM_SA));*/
2050 }
2051
2052 /*******************************************************************************
2053 * mvCesaDmaCopyPrepare - prepare DMA descriptor list to copy data presented by
2054 * Mbuf structure from DRAM to SRAM
2055 *
2056 * DESCRIPTION:
2057 *
2058 *
2059 * INPUT:
2060 * MV_CESA_MBUF* pMbuf - pointer to Mbuf structure contains request
2061 * data in DRAM
2062 * MV_U8* pSramBuf - pointer to buffer in SRAM where data should
2063 * be copied to.
2064 * MV_DMA_DESC* pDmaDesc - pointer to first DMA descriptor for this copy.
2065 * The function set number of DMA descriptors needed
2066 * to copy the copySize bytes from Mbuf.
2067 * MV_BOOL isToMbuf - Copy direction.
2068 * MV_TRUE means copy from SRAM buffer to Mbuf in DRAM.
2069 * MV_FALSE means copy from Mbuf in DRAM to SRAM buffer.
2070 * int offset - Offset in the Mbuf structure that copy should be
2071 * started from.
2072 * int copySize - Size of data should be copied.
2073 *
2074 * RETURN:
2075 * int - number of DMA descriptors used for the copy.
2076 *
2077 *******************************************************************************/
2078 #ifndef MV_NETBSD
2079 static INLINE int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
2080 MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
2081 int offset, int copySize, MV_BOOL skipFlush)
2082 {
2083 int bufOffset, bufSize, size, frag, i;
2084 MV_U8* pBuf;
2085
2086 i = 0;
2087
2088 /* Calculate start place for copy: fragment number and offset in the fragment */
2089 frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset);
2090 bufSize = pMbuf->pFrags[frag].bufSize - bufOffset;
2091 pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset;
2092
2093 /* Size accumulate total copy size */
2094 size = 0;
2095
2096 /* Create DMA lists to copy mBuf from pSrc to SRAM */
2097 while(size < copySize)
2098 {
2099 /* Find copy size for each DMA descriptor */
2100 bufSize = MV_MIN(bufSize, (copySize - size));
2101 pDmaDesc[i].byteCnt = MV_32BIT_LE(bufSize | BIT31);
2102 if(isToMbuf)
2103 {
2104 pDmaDesc[i].phyDestAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
2105 pDmaDesc[i].phySrcAdd =
2106 MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size)));
2107 /* invalidate the buffer */
2108 if(skipFlush == MV_FALSE)
2109 mvOsCacheInvalidate(NULL, pBuf, bufSize);
2110 }
2111 else
2112 {
2113 pDmaDesc[i].phySrcAdd = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
2114 pDmaDesc[i].phyDestAdd =
2115 MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (pSramBuf + size)));
2116 /* flush the buffer */
2117 if(skipFlush == MV_FALSE)
2118 mvOsCacheFlush(NULL, pBuf, bufSize);
2119 }
2120
2121 /* Count number of used DMA descriptors */
2122 i++;
2123 size += bufSize;
2124
2125 /* go to next fragment in the Mbuf */
2126 frag++;
2127 pBuf = pMbuf->pFrags[frag].bufVirtPtr;
2128 bufSize = pMbuf->pFrags[frag].bufSize;
2129 }
2130 return i;
2131 }
2132 #else /* MV_NETBSD */
2133 static int mvCesaDmaCopyPrepare(MV_CESA_MBUF* pMbuf, MV_U8* pSramBuf,
2134 MV_DMA_DESC* pDmaDesc, MV_BOOL isToMbuf,
2135 int offset, int copySize, MV_BOOL skipFlush)
2136 {
2137 int bufOffset, bufSize, thisSize, size, frag, i;
2138 MV_ULONG bufPhys, sramPhys;
2139 MV_U8* pBuf;
2140
2141 /*
2142 * Calculate start place for copy: fragment number and offset in
2143 * the fragment
2144 */
2145 frag = mvCesaMbufOffset(pMbuf, offset, &bufOffset);
2146
2147 /*
2148 * Get SRAM physical address only once. We can update it in-place
2149 * as we build the descriptor chain.
2150 */
2151 sramPhys = mvCesaSramVirtToPhys(NULL, pSramBuf);
2152
2153 /*
2154 * 'size' accumulates total copy size, 'i' counts desccriptors.
2155 */
2156 size = i = 0;
2157
2158 /* Create DMA lists to copy mBuf from pSrc to SRAM */
2159 while (size < copySize) {
2160 /*
2161 * Calculate # of bytes to copy from the current fragment,
2162 * and the pointer to the start of data
2163 */
2164 bufSize = pMbuf->pFrags[frag].bufSize - bufOffset;
2165 pBuf = pMbuf->pFrags[frag].bufVirtPtr + bufOffset;
2166 bufOffset = 0; /* First frag may be non-zero */
2167 frag++;
2168
2169 /*
2170 * As long as there is data in the current fragment...
2171 */
2172 while (bufSize > 0) {
2173 /*
2174 * Ensure we don't cross an MMU page boundary.
2175 * XXX: This is NetBSD-specific, but it is a
2176 * quick and dirty way to fix the problem.
2177 * A true HAL would rely on the OS-specific
2178 * driver to do this...
2179 */
2180 thisSize = PAGE_SIZE -
2181 (((MV_ULONG)pBuf) & (PAGE_SIZE - 1));
2182 thisSize = MV_MIN(bufSize, thisSize);
2183 /*
2184 * Make sure we don't copy more than requested
2185 */
2186 if (thisSize > (copySize - size)) {
2187 thisSize = copySize - size;
2188 bufSize = 0;
2189 }
2190
2191 /*
2192 * Physicall address of this fragment
2193 */
2194 bufPhys = MV_32BIT_LE(mvOsIoVirtToPhy(NULL, pBuf));
2195
2196 /*
2197 * Set up the descriptor
2198 */
2199 pDmaDesc[i].byteCnt = MV_32BIT_LE(thisSize | BIT31);
2200 if(isToMbuf) {
2201 pDmaDesc[i].phyDestAdd = bufPhys;
2202 pDmaDesc[i].phySrcAdd = MV_32BIT_LE(sramPhys);
2203 /* invalidate the buffer */
2204 if(skipFlush == MV_FALSE)
2205 mvOsCacheInvalidate(NULL, pBuf, thisSize);
2206 } else {
2207 pDmaDesc[i].phySrcAdd = bufPhys;
2208 pDmaDesc[i].phyDestAdd = MV_32BIT_LE(sramPhys);
2209 /* flush the buffer */
2210 if(skipFlush == MV_FALSE)
2211 mvOsCacheFlush(NULL, pBuf, thisSize);
2212 }
2213
2214 pDmaDesc[i].phyNextDescPtr =
2215 MV_32BIT_LE(mvOsIoVirtToPhy(NULL,(&pDmaDesc[i+1])));
2216
2217 /* flush the DMA desc */
2218 mvOsCacheFlush(NULL, &pDmaDesc[i], sizeof(MV_DMA_DESC));
2219
2220 /* Update state */
2221 bufSize -= thisSize;
2222 sramPhys += thisSize;
2223 pBuf += thisSize;
2224 size += thisSize;
2225 i++;
2226 }
2227 }
2228
2229 return i;
2230 }
2231 #endif /* MV_NETBSD */
2232 /*******************************************************************************
2233 * mvCesaHmacIvGet - Calculate Inner and Outter values from HMAC key
2234 *
2235 * DESCRIPTION:
2236 * This function calculate Inner and Outer values used for HMAC algorithm.
2237 * This operation allows improve performance fro the whole HMAC processing.
2238 *
2239 * INPUT:
2240 * MV_CESA_MAC_MODE macMode - Authentication mode: HMAC_MD5 or HMAC_SHA1.
2241 * unsigned char key[] - Pointer to HMAC key.
2242 * int keyLength - Size of HMAC key (maximum 64 bytes)
2243 *
2244 * OUTPUT:
2245 * unsigned char innerIV[] - HASH(key^inner)
2246 * unsigned char outerIV[] - HASH(key^outter)
2247 *
2248 * RETURN: None
2249 *
2250 *******************************************************************************/
2251 static void mvCesaHmacIvGet(MV_CESA_MAC_MODE macMode, unsigned char key[], int keyLength,
2252 unsigned char innerIV[], unsigned char outerIV[])
2253 {
2254 unsigned char inner[MV_CESA_MAX_MAC_KEY_LENGTH];
2255 unsigned char outer[MV_CESA_MAX_MAC_KEY_LENGTH];
2256 int i, digestSize = 0;
2257 #if defined(MV_CPU_LE) || defined(MV_PPC)
2258 MV_U32 swapped32, val32, *pVal32;
2259 #endif
2260 for(i=0; i<keyLength; i++)
2261 {
2262 inner[i] = 0x36 ^ key[i];
2263 outer[i] = 0x5c ^ key[i];
2264 }
2265
2266 for(i=keyLength; i<MV_CESA_MAX_MAC_KEY_LENGTH; i++)
2267 {
2268 inner[i] = 0x36;
2269 outer[i] = 0x5c;
2270 }
2271 if(macMode == MV_CESA_MAC_HMAC_MD5)
2272 {
2273 MV_MD5_CONTEXT ctx;
2274
2275 mvMD5Init(&ctx);
2276 mvMD5Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
2277
2278 memcpy(innerIV, ctx.buf, MV_CESA_MD5_DIGEST_SIZE);
2279 memset(&ctx, 0, sizeof(ctx));
2280
2281 mvMD5Init(&ctx);
2282 mvMD5Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
2283 memcpy(outerIV, ctx.buf, MV_CESA_MD5_DIGEST_SIZE);
2284 memset(&ctx, 0, sizeof(ctx));
2285 digestSize = MV_CESA_MD5_DIGEST_SIZE;
2286 }
2287 else if(macMode == MV_CESA_MAC_HMAC_SHA1)
2288 {
2289 MV_SHA1_CTX ctx;
2290
2291 mvSHA1Init(&ctx);
2292 mvSHA1Update(&ctx, inner, MV_CESA_MAX_MAC_KEY_LENGTH);
2293 memcpy(innerIV, ctx.state, MV_CESA_SHA1_DIGEST_SIZE);
2294 memset(&ctx, 0, sizeof(ctx));
2295
2296 mvSHA1Init(&ctx);
2297 mvSHA1Update(&ctx, outer, MV_CESA_MAX_MAC_KEY_LENGTH);
2298 memcpy(outerIV, ctx.state, MV_CESA_SHA1_DIGEST_SIZE);
2299 memset(&ctx, 0, sizeof(ctx));
2300 digestSize = MV_CESA_SHA1_DIGEST_SIZE;
2301 }
2302 else
2303 {
2304 mvOsPrintf("hmacGetIV: Unexpected macMode %d\n", macMode);
2305 }
2306 #if defined(MV_CPU_LE) || defined(MV_PPC)
2307 /* 32 bits Swap of Inner and Outer values */
2308 pVal32 = (MV_U32*)innerIV;
2309 for(i=0; i<digestSize/4; i++)
2310 {
2311 val32 = *pVal32;
2312 swapped32 = MV_BYTE_SWAP_32BIT(val32);
2313 *pVal32 = swapped32;
2314 pVal32++;
2315 }
2316 pVal32 = (MV_U32*)outerIV;
2317 for(i=0; i<digestSize/4; i++)
2318 {
2319 val32 = *pVal32;
2320 swapped32 = MV_BYTE_SWAP_32BIT(val32);
2321 *pVal32 = swapped32;
2322 pVal32++;
2323 }
2324 #endif /* defined(MV_CPU_LE) || defined(MV_PPC) */
2325 }
2326
2327
2328 /*******************************************************************************
2329 * mvCesaFragSha1Complete - Complete SHA1 authentication started by HW using SW
2330 *
2331 * DESCRIPTION:
2332 *
2333 *
2334 * INPUT:
2335 * MV_CESA_MBUF* pMbuf - Pointer to Mbuf structure where data
2336 * for SHA1 is placed.
2337 * int offset - Offset in the Mbuf structure where
2338 * unprocessed data for SHA1 is started.
2339 * MV_U8* pOuterIV - Pointer to OUTER for this session.
2340 * If pOuterIV==NULL - MAC mode is HASH_SHA1
2341 * If pOuterIV!=NULL - MAC mode is HMAC_SHA1
2342 * int macLeftSize - Size of unprocessed data for SHA1.
2343 * int macTotalSize - Total size of data for SHA1 in the
2344 * request (processed + unprocessed)
2345 *
2346 * OUTPUT:
2347 * MV_U8* pDigest - Pointer to place where calculated Digest will
2348 * be stored.
2349 *
2350 * RETURN: None
2351 *
2352 *******************************************************************************/
2353 static void mvCesaFragSha1Complete(MV_CESA_MBUF* pMbuf, int offset,
2354 MV_U8* pOuterIV, int macLeftSize,
2355 int macTotalSize, MV_U8* pDigest)
2356 {
2357 MV_SHA1_CTX ctx;
2358 MV_U8 *pData;
2359 int i, frag, fragOffset, size;
2360
2361 /* Read temporary Digest from HW */
2362 for(i=0; i<MV_CESA_SHA1_DIGEST_SIZE/4; i++)
2363 {
2364 ctx.state[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(i));
2365 }
2366 /* Initialize MV_SHA1_CTX structure */
2367 memset(ctx.buffer, 0, 64);
2368 /* Set count[0] in bits. 32 bits is enough for 512 MBytes */
2369 /* so count[1] is always 0 */
2370 ctx.count[0] = ((macTotalSize - macLeftSize) * 8);
2371 ctx.count[1] = 0;
2372
2373 /* If HMAC - add size of Inner block (64 bytes) ro count[0] */
2374 if(pOuterIV != NULL)
2375 ctx.count[0] += (64 * 8);
2376
2377 /* Get place of unprocessed data in the Mbuf structure */
2378 frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
2379 if(frag == MV_INVALID)
2380 {
2381 mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
2382 return;
2383 }
2384
2385 pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
2386 size = pMbuf->pFrags[frag].bufSize - fragOffset;
2387
2388 /* Complete Inner part */
2389 while(macLeftSize > 0)
2390 {
2391 if(macLeftSize <= size)
2392 {
2393 mvSHA1Update(&ctx, pData, macLeftSize);
2394 break;
2395 }
2396 mvSHA1Update(&ctx, pData, size);
2397 macLeftSize -= size;
2398 frag++;
2399 pData = pMbuf->pFrags[frag].bufVirtPtr;
2400 size = pMbuf->pFrags[frag].bufSize;
2401 }
2402 mvSHA1Final(pDigest, &ctx);
2403 /*
2404 mvOsPrintf("mvCesaFragSha1Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
2405 pOuterIV, macLeftSize, macTotalSize);
2406 mvDebugMemDump(pDigest, MV_CESA_SHA1_DIGEST_SIZE, 1);
2407 */
2408
2409 if(pOuterIV != NULL)
2410 {
2411 /* If HMAC - Complete Outer part */
2412 for(i=0; i<MV_CESA_SHA1_DIGEST_SIZE/4; i++)
2413 {
2414 #if defined(MV_CPU_LE) || defined(MV_ARM)
2415 ctx.state[i] = MV_BYTE_SWAP_32BIT(((MV_U32*)pOuterIV)[i]);
2416 #else
2417 ctx.state[i] = ((MV_U32*)pOuterIV)[i];
2418 #endif
2419 }
2420 memset(ctx.buffer, 0, 64);
2421
2422 ctx.count[0] = 64*8;
2423 ctx.count[1] = 0;
2424 mvSHA1Update(&ctx, pDigest, MV_CESA_SHA1_DIGEST_SIZE);
2425 mvSHA1Final(pDigest, &ctx);
2426 }
2427 }
2428
2429 /*******************************************************************************
2430 * mvCesaFragMd5Complete - Complete MD5 authentication started by HW using SW
2431 *
2432 * DESCRIPTION:
2433 *
2434 *
2435 * INPUT:
2436 * MV_CESA_MBUF* pMbuf - Pointer to Mbuf structure where data
2437 * for SHA1 is placed.
2438 * int offset - Offset in the Mbuf structure where
2439 * unprocessed data for MD5 is started.
2440 * MV_U8* pOuterIV - Pointer to OUTER for this session.
2441 * If pOuterIV==NULL - MAC mode is HASH_MD5
2442 * If pOuterIV!=NULL - MAC mode is HMAC_MD5
2443 * int macLeftSize - Size of unprocessed data for MD5.
2444 * int macTotalSize - Total size of data for MD5 in the
2445 * request (processed + unprocessed)
2446 *
2447 * OUTPUT:
2448 * MV_U8* pDigest - Pointer to place where calculated Digest will
2449 * be stored.
2450 *
2451 * RETURN: None
2452 *
2453 *******************************************************************************/
2454 static void mvCesaFragMd5Complete(MV_CESA_MBUF* pMbuf, int offset,
2455 MV_U8* pOuterIV, int macLeftSize,
2456 int macTotalSize, MV_U8* pDigest)
2457 {
2458 MV_MD5_CONTEXT ctx;
2459 MV_U8 *pData;
2460 int i, frag, fragOffset, size;
2461
2462 /* Read temporary Digest from HW */
2463 for(i=0; i<MV_CESA_MD5_DIGEST_SIZE/4; i++)
2464 {
2465 ctx.buf[i] = MV_REG_READ(MV_CESA_AUTH_INIT_VAL_DIGEST_REG(i));
2466 }
2467 memset(ctx.in, 0, 64);
2468
2469 /* Set count[0] in bits. 32 bits is enough for 512 MBytes */
2470 /* so count[1] is always 0 */
2471 ctx.bits[0] = ((macTotalSize - macLeftSize) * 8);
2472 ctx.bits[1] = 0;
2473
2474 /* If HMAC - add size of Inner block (64 bytes) ro count[0] */
2475 if(pOuterIV != NULL)
2476 ctx.bits[0] += (64 * 8);
2477
2478 frag = mvCesaMbufOffset(pMbuf, offset, &fragOffset);
2479 if(frag == MV_INVALID)
2480 {
2481 mvOsPrintf("CESA Mbuf Error: offset (%d) out of range\n", offset);
2482 return;
2483 }
2484
2485 pData = pMbuf->pFrags[frag].bufVirtPtr + fragOffset;
2486 size = pMbuf->pFrags[frag].bufSize - fragOffset;
2487
2488 /* Complete Inner part */
2489 while(macLeftSize > 0)
2490 {
2491 if(macLeftSize <= size)
2492 {
2493 mvMD5Update(&ctx, pData, macLeftSize);
2494 break;
2495 }
2496 mvMD5Update(&ctx, pData, size);
2497 macLeftSize -= size;
2498 frag++;
2499 pData = pMbuf->pFrags[frag].bufVirtPtr;
2500 size = pMbuf->pFrags[frag].bufSize;
2501 }
2502 mvMD5Final(pDigest, &ctx);
2503
2504 /*
2505 mvOsPrintf("mvCesaFragMd5Complete: pOuterIV=%p, macLeftSize=%d, macTotalSize=%d\n",
2506 pOuterIV, macLeftSize, macTotalSize);
2507 mvDebugMemDump(pDigest, MV_CESA_MD5_DIGEST_SIZE, 1);
2508 */
2509 if(pOuterIV != NULL)
2510 {
2511 /* Complete Outer part */
2512 for(i=0; i<MV_CESA_MD5_DIGEST_SIZE/4; i++)
2513 {
2514 #if defined(MV_CPU_LE) || defined(MV_ARM)
2515 ctx.buf[i] = MV_BYTE_SWAP_32BIT(((MV_U32*)pOuterIV)[i]);
2516 #else
2517 ctx.buf[i] = ((MV_U32*)pOuterIV)[i];
2518 #endif
2519 }
2520 memset(ctx.in, 0, 64);
2521
2522 ctx.bits[0] = 64*8;
2523 ctx.bits[1] = 0;
2524 mvMD5Update(&ctx, pDigest, MV_CESA_MD5_DIGEST_SIZE);
2525 mvMD5Final(pDigest, &ctx);
2526 }
2527 }
2528
2529 /*******************************************************************************
2530 * mvCesaFragAuthComplete -
2531 *
2532 * DESCRIPTION:
2533 *
2534 *
2535 * INPUT:
2536 * MV_CESA_REQ* pReq,
2537 * MV_CESA_SA* pSA,
2538 * int macDataSize
2539 *
2540 * RETURN:
2541 * MV_STATUS
2542 *
2543 *******************************************************************************/
2544 static MV_STATUS mvCesaFragAuthComplete(MV_CESA_REQ* pReq, MV_CESA_SA* pSA,
2545 int macDataSize)
2546 {
2547 MV_CESA_COMMAND* pCmd = pReq->pCmd;
2548 MV_U8* pDigest;
2549 MV_CESA_MAC_MODE macMode;
2550 MV_U8* pOuterIV = NULL;
2551
2552 /* Copy data from Source fragment to Destination */
2553 if(pCmd->pSrc != pCmd->pDst)
2554 {
2555 mvCesaMbufCopy(pCmd->pDst, pReq->frags.bufOffset,
2556 pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
2557 }
2558
2559 /*
2560 mvCesaCopyFromMbuf(cesaSramVirtPtr->buf[0], pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
2561 mvCesaCopyToMbuf(cesaSramVirtPtr->buf[0], pCmd->pDst, pReq->frags.bufOffset, macDataSize);
2562 */
2563 pDigest = (mvCesaSramAddrGet() + pReq->frags.newDigestOffset);
2564
2565 macMode = (pSA->config & MV_CESA_MAC_MODE_MASK) >> MV_CESA_MAC_MODE_OFFSET;
2566 /*
2567 mvOsPrintf("macDataSize=%d, macLength=%d, digestOffset=%d, macMode=%d\n",
2568 macDataSize, pCmd->macLength, pCmd->digestOffset, macMode);
2569 */
2570 switch(macMode)
2571 {
2572 case MV_CESA_MAC_HMAC_MD5:
2573 pOuterIV = pSA->pSramSA->macOuterIV;
2574
2575 case MV_CESA_MAC_MD5:
2576 mvCesaFragMd5Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
2577 macDataSize, pCmd->macLength, pDigest);
2578 break;
2579
2580 case MV_CESA_MAC_HMAC_SHA1:
2581 pOuterIV = pSA->pSramSA->macOuterIV;
2582
2583 case MV_CESA_MAC_SHA1:
2584 mvCesaFragSha1Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
2585 macDataSize, pCmd->macLength, pDigest);
2586 break;
2587
2588 default:
2589 mvOsPrintf("mvCesaFragAuthComplete: Unexpected macMode %d\n", macMode);
2590 return MV_BAD_PARAM;
2591 }
2592 return MV_OK;
2593 }
2594
2595 /*******************************************************************************
2596 * mvCesaCtrModeInit -
2597 *
2598 * DESCRIPTION:
2599 *
2600 *
2601 * INPUT: NONE
2602 *
2603 *
2604 * RETURN:
2605 * MV_CESA_COMMAND*
2606 *
2607 *******************************************************************************/
2608 static MV_CESA_COMMAND* mvCesaCtrModeInit(void)
2609 {
2610 MV_CESA_MBUF *pMbuf;
2611 MV_U8 *pBuf;
2612 MV_CESA_COMMAND *pCmd;
2613
2614 pBuf = mvOsMalloc(sizeof(MV_CESA_COMMAND) +
2615 sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) + 100);
2616 if(pBuf == NULL)
2617 {
2618 mvOsPrintf("mvCesaSessionOpen: Can't allocate %u bytes for CTR Mode\n",
2619 sizeof(MV_CESA_COMMAND) + sizeof(MV_CESA_MBUF) + sizeof(MV_BUF_INFO) );
2620 return NULL;
2621 }
2622 pCmd = (MV_CESA_COMMAND*)pBuf;
2623 pBuf += sizeof(MV_CESA_COMMAND);
2624
2625 pMbuf = (MV_CESA_MBUF*)pBuf;
2626 pBuf += sizeof(MV_CESA_MBUF);
2627
2628 pMbuf->pFrags = (MV_BUF_INFO*)pBuf;
2629
2630 pMbuf->numFrags = 1;
2631 pCmd->pSrc = pMbuf;
2632 pCmd->pDst = pMbuf;
2633 /*
2634 mvOsPrintf("CtrModeInit: pCmd=%p, pSrc=%p, pDst=%p, pFrags=%p\n",
2635 pCmd, pCmd->pSrc, pCmd->pDst,
2636 pMbuf->pFrags);
2637 */
2638 return pCmd;
2639 }
2640
2641 /*******************************************************************************
2642 * mvCesaCtrModePrepare -
2643 *
2644 * DESCRIPTION:
2645 *
2646 *
2647 * INPUT:
2648 * MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd
2649 *
2650 * RETURN:
2651 * MV_STATUS
2652 *
2653 *******************************************************************************/
2654 static MV_STATUS mvCesaCtrModePrepare(MV_CESA_COMMAND *pCtrModeCmd, MV_CESA_COMMAND *pCmd)
2655 {
2656 MV_CESA_MBUF *pMbuf;
2657 MV_U8 *pBuf, *pIV;
2658 MV_U32 counter, *pCounter;
2659 int cryptoSize = MV_ALIGN_UP(pCmd->cryptoLength, MV_CESA_AES_BLOCK_SIZE);
2660 /*
2661 mvOsPrintf("CtrModePrepare: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n",
2662 pCmd, pCmd->pSrc, pCmd->pDst,
2663 pCtrModeCmd, pCtrModeCmd->pSrc, pCtrModeCmd->pDst);
2664 */
2665 pMbuf = pCtrModeCmd->pSrc;
2666
2667 /* Allocate buffer for Key stream */
2668 pBuf = mvOsIoCachedMalloc(cesaOsHandle,cryptoSize,
2669 &pMbuf->pFrags[0].bufPhysAddr,
2670 &pMbuf->pFrags[0].memHandle);
2671 if(pBuf == NULL)
2672 {
2673 mvOsPrintf("mvCesaCtrModePrepare: Can't allocate %d bytes\n", cryptoSize);
2674 return MV_OUT_OF_CPU_MEM;
2675 }
2676 memset(pBuf, 0, cryptoSize);
2677 mvOsCacheFlush(NULL, pBuf, cryptoSize);
2678
2679 pMbuf->pFrags[0].bufVirtPtr = pBuf;
2680 pMbuf->mbufSize = cryptoSize;
2681 pMbuf->pFrags[0].bufSize = cryptoSize;
2682
2683 pCtrModeCmd->pReqPrv = pCmd->pReqPrv;
2684 pCtrModeCmd->sessionId = pCmd->sessionId;
2685
2686 /* ivFromUser and ivOffset are don't care */
2687 pCtrModeCmd->cryptoOffset = 0;
2688 pCtrModeCmd->cryptoLength = cryptoSize;
2689
2690 /* digestOffset, macOffset and macLength are don't care */
2691
2692 mvCesaCopyFromMbuf(pBuf, pCmd->pSrc, pCmd->ivOffset, MV_CESA_AES_BLOCK_SIZE);
2693 pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter)));
2694 counter = *pCounter;
2695 counter = MV_32BIT_BE(counter);
2696 pIV = pBuf;
2697 cryptoSize -= MV_CESA_AES_BLOCK_SIZE;
2698
2699 /* fill key stream */
2700 while(cryptoSize > 0)
2701 {
2702 pBuf += MV_CESA_AES_BLOCK_SIZE;
2703 memcpy(pBuf, pIV, MV_CESA_AES_BLOCK_SIZE - sizeof(counter));
2704 pCounter = (MV_U32*)(pBuf + (MV_CESA_AES_BLOCK_SIZE - sizeof(counter)));
2705 counter++;
2706 *pCounter = MV_32BIT_BE(counter);
2707 cryptoSize -= MV_CESA_AES_BLOCK_SIZE;
2708 }
2709
2710 return MV_OK;
2711 }
2712
2713 /*******************************************************************************
2714 * mvCesaCtrModeComplete -
2715 *
2716 * DESCRIPTION:
2717 *
2718 *
2719 * INPUT:
2720 * MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd
2721 *
2722 * RETURN:
2723 * MV_STATUS
2724 *
2725 *******************************************************************************/
2726 static MV_STATUS mvCesaCtrModeComplete(MV_CESA_COMMAND *pOrgCmd, MV_CESA_COMMAND *pCmd)
2727 {
2728 int srcFrag, dstFrag, srcOffset, dstOffset, keyOffset, srcSize, dstSize;
2729 int cryptoSize = pCmd->cryptoLength;
2730 MV_U8 *pSrc, *pDst, *pKey;
2731 MV_STATUS status = MV_OK;
2732 /*
2733 mvOsPrintf("CtrModeComplete: pCmd=%p, pCtrSrc=%p, pCtrDst=%p, pOrgCmd=%p, pOrgSrc=%p, pOrgDst=%p\n",
2734 pCmd, pCmd->pSrc, pCmd->pDst,
2735 pOrgCmd, pOrgCmd->pSrc, pOrgCmd->pDst);
2736 */
2737 /* XOR source data with key stream to destination data */
2738 pKey = pCmd->pDst->pFrags[0].bufVirtPtr;
2739 keyOffset = 0;
2740
2741 if( (pOrgCmd->pSrc != pOrgCmd->pDst) &&
2742 (pOrgCmd->cryptoOffset > 0) )
2743 {
2744 /* Copy Prefix from source buffer to destination buffer */
2745
2746 status = mvCesaMbufCopy(pOrgCmd->pDst, 0,
2747 pOrgCmd->pSrc, 0, pOrgCmd->cryptoOffset);
2748 /*
2749 status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc,
2750 0, pOrgCmd->cryptoOffset);
2751 status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst,
2752 0, pOrgCmd->cryptoOffset);
2753 */
2754 }
2755
2756 srcFrag = mvCesaMbufOffset(pOrgCmd->pSrc, pOrgCmd->cryptoOffset, &srcOffset);
2757 pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr;
2758 srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize;
2759
2760 dstFrag = mvCesaMbufOffset(pOrgCmd->pDst, pOrgCmd->cryptoOffset, &dstOffset);
2761 pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr;
2762 dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize;
2763
2764 while(cryptoSize > 0)
2765 {
2766 pDst[dstOffset] = (pSrc[srcOffset] ^ pKey[keyOffset]);
2767
2768 cryptoSize--;
2769 dstOffset++;
2770 srcOffset++;
2771 keyOffset++;
2772
2773 if(srcOffset >= srcSize)
2774 {
2775 srcFrag++;
2776 srcOffset = 0;
2777 pSrc = pOrgCmd->pSrc->pFrags[srcFrag].bufVirtPtr;
2778 srcSize = pOrgCmd->pSrc->pFrags[srcFrag].bufSize;
2779 }
2780
2781 if(dstOffset >= dstSize)
2782 {
2783 dstFrag++;
2784 dstOffset = 0;
2785 pDst = pOrgCmd->pDst->pFrags[dstFrag].bufVirtPtr;
2786 dstSize = pOrgCmd->pDst->pFrags[dstFrag].bufSize;
2787 }
2788 }
2789
2790 if(pOrgCmd->pSrc != pOrgCmd->pDst)
2791 {
2792 /* Copy Suffix from source buffer to destination buffer */
2793 srcOffset = pOrgCmd->cryptoOffset + pOrgCmd->cryptoLength;
2794
2795 if( (pOrgCmd->pDst->mbufSize - srcOffset) > 0)
2796 {
2797 status = mvCesaMbufCopy(pOrgCmd->pDst, srcOffset,
2798 pOrgCmd->pSrc, srcOffset,
2799 pOrgCmd->pDst->mbufSize - srcOffset);
2800 }
2801
2802 /*
2803 status = mvCesaCopyFromMbuf(tempBuf, pOrgCmd->pSrc,
2804 srcOffset, pOrgCmd->pSrc->mbufSize - srcOffset);
2805 status = mvCesaCopyToMbuf(tempBuf, pOrgCmd->pDst,
2806 srcOffset, pOrgCmd->pDst->mbufSize - srcOffset);
2807 */
2808 }
2809
2810 /* Free buffer used for Key stream */
2811 mvOsIoCachedFree(cesaOsHandle,pCmd->pDst->pFrags[0].bufSize,
2812 pCmd->pDst->pFrags[0].bufPhysAddr,
2813 pCmd->pDst->pFrags[0].bufVirtPtr,
2814 pCmd->pDst->pFrags[0].memHandle);
2815
2816 return MV_OK;
2817 }
2818
2819 /*******************************************************************************
2820 * mvCesaCtrModeFinish -
2821 *
2822 * DESCRIPTION:
2823 *
2824 *
2825 * INPUT:
2826 * MV_CESA_COMMAND* pCmd
2827 *
2828 * RETURN:
2829 * MV_STATUS
2830 *
2831 *******************************************************************************/
2832 static void mvCesaCtrModeFinish(MV_CESA_COMMAND* pCmd)
2833 {
2834 mvOsFree(pCmd);
2835 }
2836
2837 /*******************************************************************************
2838 * mvCesaParamCheck -
2839 *
2840 * DESCRIPTION:
2841 *
2842 *
2843 * INPUT:
2844 * MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd, MV_U8* pFixOffset
2845 *
2846 * RETURN:
2847 * MV_STATUS
2848 *
2849 *******************************************************************************/
2850 static MV_STATUS mvCesaParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd,
2851 MV_U8* pFixOffset)
2852 {
2853 MV_U8 fixOffset = 0xFF;
2854
2855 /* Check AUTH operation parameters */
2856 if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
2857 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) )
2858 {
2859 /* MAC offset should be at least 4 byte aligned */
2860 if( MV_IS_NOT_ALIGN(pCmd->macOffset, 4) )
2861 {
2862 mvOsPrintf("mvCesaAction: macOffset %d must be 4 byte aligned\n",
2863 pCmd->macOffset);
2864 return MV_BAD_PARAM;
2865 }
2866 /* Digest offset must be 4 byte aligned */
2867 if( MV_IS_NOT_ALIGN(pCmd->digestOffset, 4) )
2868 {
2869 mvOsPrintf("mvCesaAction: digestOffset %d must be 4 byte aligned\n",
2870 pCmd->digestOffset);
2871 return MV_BAD_PARAM;
2872 }
2873 /* In addition all offsets should be the same alignment: 8 or 4 */
2874 if(fixOffset == 0xFF)
2875 {
2876 fixOffset = (pCmd->macOffset % 8);
2877 }
2878 else
2879 {
2880 if( (pCmd->macOffset % 8) != fixOffset)
2881 {
2882 mvOsPrintf("mvCesaAction: macOffset %d mod 8 must be equal %d\n",
2883 pCmd->macOffset, fixOffset);
2884 return MV_BAD_PARAM;
2885 }
2886 }
2887 if( (pCmd->digestOffset % 8) != fixOffset)
2888 {
2889 mvOsPrintf("mvCesaAction: digestOffset %d mod 8 must be equal %d\n",
2890 pCmd->digestOffset, fixOffset);
2891 return MV_BAD_PARAM;
2892 }
2893 }
2894 /* Check CRYPTO operation parameters */
2895 if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
2896 (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) )
2897 {
2898 /* CryptoOffset should be at least 4 byte aligned */
2899 if( MV_IS_NOT_ALIGN(pCmd->cryptoOffset, 4) )
2900 {
2901 mvOsPrintf("CesaAction: cryptoOffset=%d must be 4 byte aligned\n",
2902 pCmd->cryptoOffset);
2903 return MV_BAD_PARAM;
2904 }
2905 /* cryptoLength should be the whole number of blocks */
2906 if( MV_IS_NOT_ALIGN(pCmd->cryptoLength, pSA->cryptoBlockSize) )
2907 {
2908 mvOsPrintf("mvCesaAction: cryptoLength=%d must be %d byte aligned\n",
2909 pCmd->cryptoLength, pSA->cryptoBlockSize);
2910 return MV_BAD_PARAM;
2911 }
2912 if(fixOffset == 0xFF)
2913 {
2914 fixOffset = (pCmd->cryptoOffset % 8);
2915 }
2916 else
2917 {
2918 /* In addition all offsets should be the same alignment: 8 or 4 */
2919 if( (pCmd->cryptoOffset % 8) != fixOffset)
2920 {
2921 mvOsPrintf("mvCesaAction: cryptoOffset %d mod 8 must be equal %d \n",
2922 pCmd->cryptoOffset, fixOffset);
2923 return MV_BAD_PARAM;
2924 }
2925 }
2926
2927 /* check for CBC mode */
2928 if(pSA->cryptoIvSize > 0)
2929 {
2930 /* cryptoIV must not be part of CryptoLength */
2931 if( ((pCmd->ivOffset + pSA->cryptoIvSize) > pCmd->cryptoOffset) &&
2932 (pCmd->ivOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) )
2933 {
2934 mvOsPrintf("mvCesaFragParamCheck: cryptoIvOffset (%d) is part of cryptoLength (%d+%d)\n",
2935 pCmd->ivOffset, pCmd->macOffset, pCmd->macLength);
2936 return MV_BAD_PARAM;
2937 }
2938
2939 /* ivOffset must be 4 byte aligned */
2940 if( MV_IS_NOT_ALIGN(pCmd->ivOffset, 4) )
2941 {
2942 mvOsPrintf("CesaAction: ivOffset=%d must be 4 byte aligned\n",
2943 pCmd->ivOffset);
2944 return MV_BAD_PARAM;
2945 }
2946 /* In addition all offsets should be the same alignment: 8 or 4 */
2947 if( (pCmd->ivOffset % 8) != fixOffset)
2948 {
2949 mvOsPrintf("mvCesaAction: ivOffset %d mod 8 must be %d\n",
2950 pCmd->ivOffset, fixOffset);
2951 return MV_BAD_PARAM;
2952 }
2953 }
2954 }
2955 return MV_OK;
2956 }
2957
2958 /*******************************************************************************
2959 * mvCesaFragParamCheck -
2960 *
2961 * DESCRIPTION:
2962 *
2963 *
2964 * INPUT:
2965 * MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd
2966 *
2967 * RETURN:
2968 * MV_STATUS
2969 *
2970 *******************************************************************************/
2971 static MV_STATUS mvCesaFragParamCheck(MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd)
2972 {
2973 int offset;
2974
2975 if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
2976 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET)) )
2977 {
2978 /* macOffset must be less that SRAM buffer size */
2979 if(pCmd->macOffset > (sizeof(cesaSramVirtPtr->buf) - MV_CESA_AUTH_BLOCK_SIZE))
2980 {
2981 mvOsPrintf("mvCesaFragParamCheck: macOffset is too large (%d)\n",
2982 pCmd->macOffset);
2983 return MV_BAD_PARAM;
2984 }
2985 /* macOffset+macSize must be more than mbufSize - SRAM buffer size */
2986 if( ((pCmd->macOffset + pCmd->macLength) > pCmd->pSrc->mbufSize) ||
2987 ((pCmd->pSrc->mbufSize - (pCmd->macOffset + pCmd->macLength)) >=
2988 sizeof(cesaSramVirtPtr->buf)) )
2989 {
2990 mvOsPrintf("mvCesaFragParamCheck: macLength is too large (%d), mbufSize=%d\n",
2991 pCmd->macLength, pCmd->pSrc->mbufSize);
2992 return MV_BAD_PARAM;
2993 }
2994 }
2995
2996 if( ((pSA->config & MV_CESA_OPERATION_MASK) !=
2997 (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET)) )
2998 {
2999 /* cryptoOffset must be less that SRAM buffer size */
3000 /* 4 for possible fixOffset */
3001 if( (pCmd->cryptoOffset + 4) > (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize))
3002 {
3003 mvOsPrintf("mvCesaFragParamCheck: cryptoOffset is too large (%d)\n",
3004 pCmd->cryptoOffset);
3005 return MV_BAD_PARAM;
3006 }
3007
3008 /* cryptoOffset+cryptoSize must be more than mbufSize - SRAM buffer size */
3009 if( ((pCmd->cryptoOffset + pCmd->cryptoLength) > pCmd->pSrc->mbufSize) ||
3010 ((pCmd->pSrc->mbufSize - (pCmd->cryptoOffset + pCmd->cryptoLength)) >=
3011 (sizeof(cesaSramVirtPtr->buf) - pSA->cryptoBlockSize)) )
3012 {
3013 mvOsPrintf("mvCesaFragParamCheck: cryptoLength is too large (%d), mbufSize=%d\n",
3014 pCmd->cryptoLength, pCmd->pSrc->mbufSize);
3015 return MV_BAD_PARAM;
3016 }
3017 }
3018
3019 /* When MAC_THEN_CRYPTO or CRYPTO_THEN_MAC */
3020 if( ((pSA->config & MV_CESA_OPERATION_MASK) ==
3021 (MV_CESA_MAC_THEN_CRYPTO << MV_CESA_OPERATION_OFFSET)) ||
3022 ((pSA->config & MV_CESA_OPERATION_MASK) ==
3023 (MV_CESA_CRYPTO_THEN_MAC << MV_CESA_OPERATION_OFFSET)) )
3024 {
3025 if( (mvCtrlModelGet() == MV_5182_DEV_ID) ||
3026 ( (mvCtrlModelGet() == MV_5181_DEV_ID) &&
3027 (mvCtrlRevGet() >= MV_5181L_A0_REV) &&
3028 (pCmd->macLength >= (1 << 14)) ) )
3029 {
3030 return MV_NOT_ALLOWED;
3031 }
3032
3033 /* abs(cryptoOffset-macOffset) must be aligned cryptoBlockSize */
3034 if(pCmd->cryptoOffset > pCmd->macOffset)
3035 {
3036 offset = pCmd->cryptoOffset - pCmd->macOffset;
3037 }
3038 else
3039 {
3040 offset = pCmd->macOffset - pCmd->cryptoOffset;
3041 }
3042
3043 if( MV_IS_NOT_ALIGN(offset, pSA->cryptoBlockSize) )
3044 {
3045 /*
3046 mvOsPrintf("mvCesaFragParamCheck: (cryptoOffset - macOffset) must be %d byte aligned\n",
3047 pSA->cryptoBlockSize);
3048 */
3049 return MV_NOT_ALLOWED;
3050 }
3051 /* Digest must not be part of CryptoLength */
3052 if( ((pCmd->digestOffset + pSA->digestSize) > pCmd->cryptoOffset) &&
3053 (pCmd->digestOffset < (pCmd->cryptoOffset + pCmd->cryptoLength)) )
3054 {
3055 /*
3056 mvOsPrintf("mvCesaFragParamCheck: digestOffset (%d) is part of cryptoLength (%d+%d)\n",
3057 pCmd->digestOffset, pCmd->cryptoOffset, pCmd->cryptoLength);
3058 */
3059 return MV_NOT_ALLOWED;
3060 }
3061 }
3062 return MV_OK;
3063 }
3064
3065 /*******************************************************************************
3066 * mvCesaFragSizeFind -
3067 *
3068 * DESCRIPTION:
3069 *
3070 *
3071 * INPUT:
3072 * MV_CESA_SA* pSA, MV_CESA_COMMAND *pCmd,
3073 * int cryptoOffset, int macOffset,
3074 *
3075 * OUTPUT:
3076 * int* pCopySize, int* pCryptoDataSize, int* pMacDataSize
3077 *
3078 * RETURN:
3079 * MV_STATUS
3080 *
3081 *******************************************************************************/
3082 static void mvCesaFragSizeFind(MV_CESA_SA* pSA, MV_CESA_REQ* pReq,
3083 int cryptoOffset, int macOffset,
3084 int* pCopySize, int* pCryptoDataSize, int* pMacDataSize)
3085 {
3086 MV_CESA_COMMAND *pCmd = pReq->pCmd;
3087 int cryptoDataSize, macDataSize, copySize;
3088
3089 cryptoDataSize = macDataSize = 0;
3090 copySize = *pCopySize;
3091
3092 if( (pSA->config & MV_CESA_OPERATION_MASK) !=
3093 (MV_CESA_MAC_ONLY << MV_CESA_OPERATION_OFFSET) )
3094 {
3095 cryptoDataSize = MV_MIN( (copySize - cryptoOffset),
3096 (pCmd->cryptoLength - (pReq->frags.cryptoSize + 1)) );
3097
3098 /* cryptoSize for each fragment must be the whole number of blocksSize */
3099 if( MV_IS_NOT_ALIGN(cryptoDataSize, pSA->cryptoBlockSize) )
3100 {
3101 cryptoDataSize = MV_ALIGN_DOWN(cryptoDataSize, pSA->cryptoBlockSize);
3102 copySize = cryptoOffset + cryptoDataSize;
3103 }
3104 }
3105 if( (pSA->config & MV_CESA_OPERATION_MASK) !=
3106 (MV_CESA_CRYPTO_ONLY << MV_CESA_OPERATION_OFFSET) )
3107 {
3108 macDataSize = MV_MIN( (copySize - macOffset),
3109 (pCmd->macLength - (pReq->frags.macSize + 1)));
3110
3111 /* macSize for each fragment (except last) must be the whole number of blocksSize */
3112 if( MV_IS_NOT_ALIGN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE) )
3113 {
3114 macDataSize = MV_ALIGN_DOWN(macDataSize, MV_CESA_AUTH_BLOCK_SIZE);
3115 copySize = macOffset + macDataSize;
3116 }
3117 cryptoDataSize = copySize - cryptoOffset;
3118 }
3119 *pCopySize = copySize;
3120
3121 if(pCryptoDataSize != NULL)
3122 *pCryptoDataSize = cryptoDataSize;
3123
3124 if(pMacDataSize != NULL)
3125 *pMacDataSize = macDataSize;
3126 }