Пример #1
0
/*!
 * This function waits for current descriptor sequence completion.
 */
void WaitForSequenceCompletionPlat(void)
{
	int qid = CURR_QUEUE_ID();
	uint32_t taskId = CURR_TASK_ID();
	uint32_t lazyWait = 0;
	uint32_t irr = 0;
	uint32_t data = 0;

	/* Acknowledge completion to host */
	AddCompletionDesc(qid, taskId, (void *)COMPLETION_EXTERNAL);

	/* wait for descriptor completion signal */
	irr = DX_HAL_WaitInterrupt(data);
	/* clear interrupt */
	DX_HAL_WriteCcRegister(DX_CC_REG_OFFSET(HOST_RGF, HOST_RGF_ICR), irr);

	/* check for compeltion */
	while (!HW_QUEUE_NO_OS_IS_DESC_COMPLETED(irr)) {
		/* completion may be on its way... */
		if (lazyWait++ > 100) {
			DX_PAL_Abort("Completion failed to arrive for too long");
		}
		irr = DX_HAL_WaitInterrupt(data);
		/* clear interrupt */
		DX_HAL_WriteCcRegister(DX_CC_REG_OFFSET(HOST_RGF, HOST_RGF_ICR), irr);
	}
	CompletionDescHandler();
	
	//DX_PAL_LOG_INFO("Sequence completed\n");
	//PRINT_INFO("Sequence completed\n");
}
Пример #2
0
/*!
 * This function is called from the SW queue manager in order to complete
 * a crypto operation. The SW queue manager calls this API when the
 * "Process" bit "0x2" is set in the SW descriptor header. This function
 * may be invoked after "DispatchDriverProcess" or "DispatchDriverInit" with any
 * number of IN/OUT MLLI tables.
 * 
 * \param pCtx A pointer to the context buffer in SRAM.
 * \param pDmaInputBuffer A structure which represents the DMA input buffer.
 * \param pDmaOutputBuffer A structure which represents the DMA output buffer.
 * 
 * \return int One of DX_SYM_* error codes defined in head of file.
 */
int SymDriverDispatchFinalize(struct sep_ctx_generic *pCtx, DmaBuffer_s *pDmaInputBuffer, DmaBuffer_s *pDmaOutputBuffer)
{
	int retcode;	
	uint32_t alg;

	DX_PAL_LOG_INFO("qid=%d pCtx=%p\n", CURR_QUEUE_ID(), pCtx);

	DX_PAL_LOG_INFO("pDmaInputBuffer: pData=%p DataSize=%d DmaMode=%d nTables=%d\n",
			(uint32_t *)pDmaInputBuffer->pData, (int)pDmaInputBuffer->size, 
			(int)pDmaInputBuffer->dmaBufType, (int)pDmaInputBuffer->nTables);
	
	DX_PAL_LOG_INFO("pDmaOutputBuffer: pData=%p DataSize=%d DmaMode=%d nTables=%d\n",
			(uint32_t *)pDmaOutputBuffer->pData, (int)pDmaOutputBuffer->size, 
			(int)pDmaOutputBuffer->dmaBufType, (int)pDmaOutputBuffer->nTables);
	//mdelay(1000);
	alg = ReadContextWord(&pCtx->alg);
		
	if (gFuncDispatchList[alg].finalizeFunc == NULL) {
		DX_PAL_LOG_ERR("Unsupported alg %d\n", alg);
		return DX_RET_UNSUPP_ALG;
	}

	HW_QUEUE_LOCK();

	retcode = (gFuncDispatchList[alg].finalizeFunc)(pCtx, pDmaInputBuffer, pDmaOutputBuffer);

	HW_QUEUE_UNLOCK();

	return retcode;
}
Пример #3
0
/*!
 * This function is used to initialize the AES machine to perform the AES
 * operations. This should be the first function called.
 * 
 * \param pCtx A pointer to the context buffer in SRAM.
 * 
 * \return int One of DX_SYM_* error codes defined in dx_error.h.
 */
int InitCipher(struct sep_ctx_cipher *pCtx)
{
	SepCipherPrivateContext_s *pCipherPrivateCtx = (SepCipherPrivateContext_s *)pCtx->reserved;
	int qid = CURR_QUEUE_ID(); /* qid is stored in pxTaskTag field */

	if (ReadContextWord(&pCtx->alg) == SEP_CRYPTO_ALG_DES) {
	    /*in caes of double DES k1 = K3, copy k1-> K3*/
	    if (ReadContextWord(&pCtx->key_size) == SEP_DES_DOUBLE_KEY_SIZE){
#ifdef DX_CC_SRAM_INDIRECT_ACCESS
		    /*temporary buffer to allow key coping, must be aligned to words*/
		    uint32_t tKeybuff[SEP_DES_ONE_KEY_SIZE/sizeof(uint32_t)];
		    ReadContextField(pCtx->key, tKeybuff, SEP_DES_ONE_KEY_SIZE);
		    WriteContextField((pCtx->key + SEP_DES_DOUBLE_KEY_SIZE), tKeybuff, SEP_DES_ONE_KEY_SIZE);
		    WriteContextWord(&pCtx->key_size, SEP_DES_TRIPLE_KEY_SIZE);
#else
		    DX_PAL_MemCopy((pCtx->key + SEP_DES_DOUBLE_KEY_SIZE), pCtx->key, SEP_DES_ONE_KEY_SIZE);
		    pCtx->key_size = SEP_DES_TRIPLE_KEY_SIZE;
#endif
	    }
	    return DX_RET_OK;
	}

	switch (ReadContextWord(&pCtx->mode)) {
	case SEP_CIPHER_CMAC:
		ClearCtxField(pCtx->block_state, SEP_AES_BLOCK_SIZE);
		if(ReadContextWord(&pCtx->crypto_key_type) == DX_ROOT_KEY) {
			uint32_t keySize;
			GET_ROOT_KEY_SIZE(keySize);
			WriteContextWord(&pCtx->key_size,keySize);
		}
		break;
	case SEP_CIPHER_XCBC_MAC:
		if (ReadContextWord(&pCtx->key_size) != SEP_AES_128_BIT_KEY_SIZE) {
			DX_PAL_LOG_ERR("Invalid key size\n");
			return DX_RET_INVARG;
		}
		ClearCtxField(pCtx->block_state, SEP_AES_BLOCK_SIZE);
		CalcXcbcKeys(qid, pCtx);
		break;
	default:
		break;
	}
 	
	/* init private context */
	WriteContextWord(&pCipherPrivateCtx->engineCore,SEP_AES_ENGINE1);
	WriteContextWord(&pCipherPrivateCtx->isTunnelOp, TUNNEL_OFF);
	WriteContextWord(&pCipherPrivateCtx->isDataBlockProcessed,0);

	return DX_RET_OK;
}
Пример #4
0
void descriptor_log(HwDesc_s *desc)
{
	uint32_t qid;

	qid = CURR_QUEUE_ID();
	queue_log[qid][queue_log_index[qid] * HW_DESC_SIZE_WORDS + 0] = desc->word[0];
	queue_log[qid][queue_log_index[qid] * HW_DESC_SIZE_WORDS + 1] = desc->word[1];
	queue_log[qid][queue_log_index[qid] * HW_DESC_SIZE_WORDS + 2] = desc->word[2];
	queue_log[qid][queue_log_index[qid] * HW_DESC_SIZE_WORDS + 3] = desc->word[3];
	queue_log[qid][queue_log_index[qid] * HW_DESC_SIZE_WORDS + 4] = desc->word[4];

	queue_log_index[qid]++;
	queue_log_index[qid] &= (QUEUE_LOG_SIZE - 1);
}
Пример #5
0
/*!
 * This function is called from the SW queue manager which passes the
 * related context. The function casts the context buffer and diverts
 * to the specific CRYS Init API according to the cipher algorithm that
 * associated in the given context. It is also prepare the necessary
 * firmware private context parameters that are require for the crypto
 * operation, for example, computation of the AES-MAC k1, k2, k3 values.
 * The API has no affect on the user data buffers.
 * 
 * \param pCtx A pointer to the context buffer in SRAM.
 * 
 * \return int One of DX_SYM_* error codes defined in head of file.
 */
int SymDriverDispatchInit(struct sep_ctx_generic *pCtx)
{
	int retcode;
	uint32_t alg;

	DX_PAL_LOG_INFO("qid=%d pCtx=%p\n", CURR_QUEUE_ID(), pCtx);

	//mdelay(1000);
	alg = ReadContextWord(&pCtx->alg);

	if (gFuncDispatchList[alg].initFunc == NULL) {
		DX_PAL_LOG_ERR("Unsupported alg %d\n", alg);
		return DX_RET_UNSUPP_ALG;
	}

	HW_QUEUE_LOCK();

	retcode = (gFuncDispatchList[alg].initFunc)(pCtx);

	HW_QUEUE_UNLOCK();

	return retcode;
}
Пример #6
0
/*!
 * This function is used as finish operation of AES CTS mode.
 * The function may either be called after "InitCipher" or "ProcessCipher".
 * 
 * \param pCtx A pointer to the AES context buffer in SRAM.
 * \param pDmaInputBuffer A structure which represents the DMA input buffer.
 * \param pDmaOutputBuffer A structure which represents the DMA output buffer.
 * 
 * \return int One of DX_SYM_* error codes defined in dx_error.h.
 */
int ProcessCTSFinalizeCipher(struct sep_ctx_cipher *pCtx, DmaBuffer_s *pDmaInputBuffer, DmaBuffer_s *pDmaOutputBuffer)
{
	uint32_t numOfBlocks = 0;
	uint32_t DataInSize = 0;
	uint32_t lastBlockSize = 0;
	uint32_t dataSizeForDLLI = 0;
	DmaMode_t dmaMode = NO_DMA;
	uint8_t *pInputData = NULL, *pOutputData = NULL;
	uint32_t lastBlockOffset = 0,nextToLastBlkOffset = 0;
	HwDesc_s desc;
	uint8_t inAxiNs = pDmaInputBuffer->axiNs;
	uint8_t outAxiNs = pDmaOutputBuffer->axiNs;
	int qid = CURR_QUEUE_ID();
	dmaMode = DMA_BUF_TYPE_TO_MODE(pDmaInputBuffer->dmaBufType);
	int drvRc = DX_RET_OK;
	uint8_t *tempBuff= NULL;


	/*Use context buffer aw temp buffer for internal operations */
	tempBuff = pCtx->xex_key;
 
 	/* check if we have remaining data to process */
	switch (dmaMode) {
	case DMA_MLLI:
	case DMA_SRAM:
		DX_PAL_LOG_ERR("Invalid DMA mode\n");
		drvRc = DX_RET_INVARG;
		return drvRc;
	case DMA_DLLI:
		DataInSize = pDmaInputBuffer->size;		
		pInputData = (uint8_t*)pDmaInputBuffer->pData;
		pOutputData =(uint8_t*)pDmaOutputBuffer->pData;
		break;
	default:
		DX_PAL_LOG_ERR("Invalid DMA mode\n");
		drvRc = DX_RET_INVARG;
		return drvRc;
	}

	/*Calculate last block size*/
	lastBlockSize = pDmaInputBuffer->size& AES_BLOCK_MASK;

	if (lastBlockSize == 0) {
		lastBlockSize = SEP_AES_BLOCK_SIZE; 
	}
	/*Calculte dataSizeForDLLI for ProcessCipher operation*/
	if (pDmaInputBuffer->size > SEP_AES_BLOCK_SIZE){
		dataSizeForDLLI = pDmaInputBuffer->size -(lastBlockSize + SEP_AES_BLOCK_SIZE);
	}
	else if(pDmaInputBuffer->size ==SEP_AES_BLOCK_SIZE){
          	dataSizeForDLLI = SEP_AES_BLOCK_SIZE;
    	}
	/*Process data with ProcessCipher */
	if (dataSizeForDLLI>0){
		/*Update data size for ProcessCipher operation*/
		pDmaInputBuffer->size = dataSizeForDLLI;
		pDmaOutputBuffer->size = dataSizeForDLLI;
           
		/*Call ProcessCipher*/
		drvRc = ProcessCipher(pCtx, pDmaInputBuffer, pDmaOutputBuffer);
		if (drvRc != DX_RET_OK) {
			goto EndWithErr;
		}
		/*Revert original value of data szie */
		pDmaInputBuffer->size = DataInSize;
		pDmaOutputBuffer->size =DataInSize;
        
		if (DataInSize ==SEP_AES_BLOCK_SIZE) {
			return drvRc;
		}
	}
 
	/*Calculate offsets of two last blocks */
	numOfBlocks = (DataInSize + SEP_AES_BLOCK_SIZE -1)/SEP_AES_BLOCK_SIZE;
	lastBlockOffset = (numOfBlocks - 1)*SEP_AES_BLOCK_SIZE;
	nextToLastBlkOffset = lastBlockOffset - SEP_AES_BLOCK_SIZE;
	lastBlockSize = DataInSize - lastBlockOffset;
    
	/*Change mode to SEP_CIPHER_CBC*/
	WriteContextWord(&pCtx->mode ,SEP_CIPHER_CBC);
	LoadCipherState(qid, pCtx,0);
	LoadCipherKey(qid, pCtx);

	/*Initialize  context's buffer for internal use*/
	HW_DESC_INIT(&desc);
	HW_DESC_SET_DIN_CONST(&desc, 0, SEP_AES_BLOCK_SIZE*2);
	HW_DESC_SET_DOUT_SRAM(&desc, (uint32_t)pCtx->xex_key, SEP_AES_BLOCK_SIZE*2);
	HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
	AddHWDescSequence(qid, &desc);

	#ifdef DX_CONFIG_HW_RESET_CONST_SUPPORT
	    HW_DESC_INIT(&desc);
	    HW_DESC_RESET_CONST_INPUT(&desc);
	    AddHWDescSequence(qid, &desc);
	#endif

	/*Encrypt mode */
	if(ReadContextWord(&pCtx->direction) == SEP_CRYPTO_DIRECTION_ENCRYPT){
    
		/* process regular AES CBC flow on next to last block */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pInputData+nextToLastBlkOffset,SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_TYPE(&desc, dmaMode, (uint32_t)pOutputData+nextToLastBlkOffset,SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), outAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT);
		AddHWDescSequence(qid, &desc);

		/* 1. Copy next to last block to temp SRAM buff to save it*/
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc,dmaMode, (uint32_t)pOutputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_SRAM(&desc,(uint32_t)tempBuff, SEP_AES_BLOCK_SIZE); 
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);

 		/*2. Copy zero buff to place of second to last block to create zero padding */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_SRAM(&desc,(uint32_t)tempBuff + SEP_AES_BLOCK_SIZE, SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_DOUT_TYPE(&desc,dmaMode, (uint32_t)pOutputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);	
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);
        
		/*3. Copy last block to place of second to last */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc,dmaMode, (uint32_t)pInputData + lastBlockOffset, lastBlockSize, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_TYPE(&desc,dmaMode,(uint32_t)pOutputData + nextToLastBlkOffset,lastBlockSize, QID_TO_AXI_ID(qid), outAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);


  		/*4.Encrypt padded last block to temp2 buff in sram*/
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc, dmaMode,(uint32_t)pOutputData + nextToLastBlkOffset,SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_SRAM(&desc,(uint32_t)tempBuff + SEP_AES_BLOCK_SIZE, SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT);
		AddHWDescSequence(qid, &desc);
		/* Perform CTS swaping operation */
  

		/*5. Copy saved in temp1 block to place of second to last output block */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_SRAM(&desc,(uint32_t)tempBuff , SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_DOUT_TYPE(&desc,dmaMode, (uint32_t)pOutputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);	
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);

 		/*6.Copy  using BYPASS, "next to last block" to "last" block and truncate it to last block size*/
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc,dmaMode, (uint32_t)pOutputData + nextToLastBlkOffset, lastBlockSize, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_TYPE(&desc, dmaMode,(uint32_t)pOutputData + lastBlockOffset, lastBlockSize, QID_TO_AXI_ID(qid), outAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);

		/*7. Copy saved in temp2 block to place of second to last block */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_SRAM(&desc,(uint32_t)tempBuff + SEP_AES_BLOCK_SIZE , SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_DOUT_TYPE(&desc,dmaMode, (uint32_t)pOutputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);	
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);
	
	} else { /*decrypt operation*/
		
		/* Descriptor flow for Decrypt CBC CTS operation (by AlonZ):
		Decrypt the data up to block Cn-2 using regular AES-CBC; save the chaining value (output IV = Cn-2)
		Process the last one-plus-reminder blocks:
		1. BYPASS DMA blocks (Cn-1, Cn) into SRAM (Cn is a partial block of length k)
		2. Decrypt Cn-1 using AES-ECB into Dn-1
		3. BYPASS DMA 16-k last bytes of Dn-1 to the end of Cn producing Cn'
		4. Decrypt Cn' using AES-CBC (IV = Cn-2) to produce Pn-1 (in SRAM)
		5. Decrypt Cn-1 (again) using AES-CBC (IV = Cn') to produce padded Pn (in SRAM)
		6. BYPASS DMA Pn-1, Pn to output */
		
		/* 1 Save Cn-1 in temp buff (in SRAM) */		
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pInputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_SRAM(&desc,(uint32_t)tempBuff,SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);	
		 
		/*decrypt the next to last block with ECB operation*/
		/*change context aes mode to ecb*/
 		/*load key for ecb operation*/
		LoadCipherState(qid, pCtx,1);
		LoadCipherKey(qid, pCtx);
		
		/*2 perform ECB decrypt of next to last block*/
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pInputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_TYPE(&desc, dmaMode, (uint32_t)pOutputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), outAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT);
		AddHWDescSequence(qid, &desc);


		/*3. Copy Cn, using BYPASS, to 16-k last bytes of decrypted with ECB next to last block to produce Cn'*/
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc,dmaMode, pInputData + lastBlockOffset,lastBlockSize, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_TYPE(&desc, dmaMode,pOutputData + nextToLastBlkOffset, lastBlockSize, QID_TO_AXI_ID(qid), outAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);
		
		
		/*4.Decrypt Cn' using AES-CBC and save it temp buff(IV = Cn-2, that was save in ctx by TST_StoreCipherState operation) 
		  to produce Dn-1 */
		/*restore aes mode to cbc for next operations*/
		LoadCipherState(qid, pCtx,0);
		LoadCipherKey(qid, pCtx);

		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pOutputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_SRAM(&desc,(uint32_t)tempBuff + SEP_AES_BLOCK_SIZE,SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT);
		AddHWDescSequence(qid, &desc);


		/*5. Decrypt Cn-1(was saved in temp buff) again using AES-CBC (IV = Cn') to produce padded Dn (in SRAM)*/		
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_SRAM(&desc,(uint32_t)tempBuff, SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_DOUT_SRAM(&desc,(uint32_t)tempBuff,SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT);
		AddHWDescSequence(qid, &desc);

		/*6. Copy the decrypted data to output*/
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_SRAM(&desc,(uint32_t)tempBuff, SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_DOUT_TYPE(&desc, dmaMode,(uint32_t)pOutputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), outAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);

		/*copy partitial block to last block */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc,dmaMode,(uint32_t)pOutputData + nextToLastBlkOffset, lastBlockSize, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_DOUT_TYPE(&desc, dmaMode,(uint32_t)pOutputData + lastBlockOffset, lastBlockSize, QID_TO_AXI_ID(qid), outAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);

		/*Copy the last blocks Dn-1 from temp SRAM buffer to output data*/
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_SRAM(&desc,(uint32_t)tempBuff +SEP_AES_BLOCK_SIZE, SEP_AES_BLOCK_SIZE);
		HW_DESC_SET_DOUT_TYPE(&desc, dmaMode,(uint32_t)pOutputData + nextToLastBlkOffset, SEP_AES_BLOCK_SIZE, QID_TO_AXI_ID(qid), outAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
		AddHWDescSequence(qid, &desc);
	} 
EndWithErr:
	return drvRc;
}
Пример #7
0
/*!
 * This function is used as finish operation of AES on XCBC, CMAC, CBC
 * and other modes besides XTS mode.
 * The function may either be called after "InitCipher" or "ProcessCipher".
 * 
 * \param pCtx A pointer to the AES context buffer in SRAM.
 * \param pDmaInputBuffer A structure which represents the DMA input buffer.
 * \param pDmaOutputBuffer A structure which represents the DMA output buffer.
 * 
 * \return int One of DX_SYM_* error codes defined in dx_error.h.
 */
int FinalizeCipher(struct sep_ctx_cipher *pCtx, DmaBuffer_s *pDmaInputBuffer, DmaBuffer_s *pDmaOutputBuffer)
{
	uint32_t isRemainingData = 0;
	uint32_t DataInSize = 0;
	uint8_t *pInputData = NULL;
	HwDesc_s desc;
	DmaMode_t dmaMode = NO_DMA;
	uint8_t inAxiNs = pDmaInputBuffer->axiNs;
	int qid = CURR_QUEUE_ID(); /* qid is stored in pxTaskTag field */
	int drvRc = DX_RET_OK;
	SepCipherPrivateContext_s *pAesPrivateCtx = (SepCipherPrivateContext_s *)pCtx->reserved;

	HW_DESC_INIT(&desc);

	dmaMode = DMA_BUF_TYPE_TO_MODE(pDmaInputBuffer->dmaBufType);

	/* check if we have remaining data to process */
	switch (dmaMode) {
	case DMA_MLLI:
		isRemainingData = pDmaInputBuffer->nTables;
		DataInSize = 0;
		break;
	case DMA_DLLI:
	case DMA_SRAM:
		isRemainingData = (pDmaInputBuffer->size > 0) ? 1 : 0;
		DataInSize = pDmaInputBuffer->size;
		break;
	case DMA_MODE_NULL:
		break;
	default:
		DX_PAL_LOG_ERR("Invalid DMA mode\n");
		drvRc = DX_RET_INVARG;
		goto EndWithErr;
	}	
	
	switch(ReadContextWord(&pCtx->mode)) {
	case SEP_CIPHER_CMAC:
	case SEP_CIPHER_XCBC_MAC:
	{
		if (isRemainingData > 1) {
			/* this case only apply to DMA_MLLI mode! */
			pDmaInputBuffer->nTables--;
			ProcessCipher(pCtx, pDmaInputBuffer, pDmaOutputBuffer);
			PrepareNextMLLITable(qid, inAxiNs, MLLI_INPUT_TABLE);
			pInputData = (uint8_t *)GetFirstLliPtr(qid, MLLI_INPUT_TABLE);
			DataInSize = 0;
		} else if (isRemainingData == 1) {
			if (dmaMode == DMA_MLLI) {
				PrepareFirstMLLITable(qid, pDmaInputBuffer, MLLI_INPUT_TABLE);
				pInputData = (uint8_t *)GetFirstLliPtr(qid, MLLI_INPUT_TABLE);
				DataInSize = 0;
			} else {
				pInputData = (uint8_t *)pDmaInputBuffer->pData;
				DataInSize = pDmaInputBuffer->size;
			}
		}


		/* Prepare processing descriptor to be pushed after loading state+key */
		HW_DESC_INIT(&desc);
		if (isRemainingData == 0) {
			if (ReadContextWord(&pAesPrivateCtx->isDataBlockProcessed) == 0) {
				/* MAC for 0 bytes */
				HW_DESC_SET_CIPHER_MODE(&desc, ReadContextWord(&pCtx->mode));
				HW_DESC_SET_KEY_SIZE_AES(&desc, ReadContextWord(&pCtx->key_size));
				HW_DESC_SET_CMAC_SIZE0_MODE(&desc);
				HW_DESC_SET_FLOW_MODE(&desc, S_DIN_to_AES);
			} else {
				/* final with 0 data but MAC total data size > 0 */
				drvRc = RevertLastMacBlock(qid, pCtx); /* Get C[n-1]-xor-M[n] */
				if (drvRc != DX_RET_OK) {
					goto EndWithErr;
				}
				/* Finish with data==0 is identical to "final"
				   op. on the last (prev.) block (XOR with 0) */
				HW_DESC_SET_DIN_CONST(&desc, 0x00, SEP_AES_BLOCK_SIZE);
				HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT);
			}
		} else {
			HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pInputData, DataInSize, QID_TO_AXI_ID(qid), inAxiNs);
			HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT);
		}

		/* load AES key and iv length and digest */
		LoadCipherState(qid, pCtx,0);
		LoadCipherKey(qid, pCtx);

		/* Process last block */
		AddHWDescSequence(qid, &desc);
#ifdef DX_CONFIG_HW_RESET_CONST_SUPPORT
		HW_DESC_INIT(&desc);
		HW_DESC_RESET_CONST_INPUT(&desc);
		AddHWDescSequence(qid, &desc);
#endif
		/* get machine state */
		StoreCipherState(qid, pCtx);
		break;
	}
	case SEP_CIPHER_CBC_CTS:
	{ 
		/*In case of data size = SEP_AES_BLOCK_SIZE check that no blocks were processed before*/
		if ((pDmaInputBuffer->size == SEP_AES_BLOCK_SIZE)&&
		    (ReadContextWord(&pAesPrivateCtx->isDataBlockProcessed) == 1)){  
			DX_PAL_LOG_ERR("Invalid dataIn size\n");
			drvRc = DX_RET_INVARG;
			goto EndWithErr;
		}
		/*Call ProcessCTSFinalizeCipher to process AES CTS finalize operation */
		drvRc = ProcessCTSFinalizeCipher(pCtx, pDmaInputBuffer, pDmaOutputBuffer);
		if (drvRc != DX_RET_OK) {
                goto EndWithErr;
		}
		break;
	}
	default:
		if (isRemainingData) {
			/* process all tables and get state from the AES machine */
			drvRc = ProcessCipher(pCtx, pDmaInputBuffer, pDmaOutputBuffer);
			if (drvRc != DX_RET_OK) {
				goto EndWithErr;
			}
		} else if (ReadContextWord(&pCtx->mode) == SEP_CIPHER_CBC_MAC) {
			/* in-case ZERO data has processed the output would be the encrypted IV */
			if (ReadContextWord(&pAesPrivateCtx->isDataBlockProcessed) == 0) {
				/* load AES key and iv length and digest */
				LoadCipherState(qid, pCtx,0);
				LoadCipherKey(qid, pCtx);

				HW_DESC_INIT(&desc);
				HW_DESC_SET_DIN_CONST(&desc, 0x00, SEP_AES_BLOCK_SIZE);
				HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT);
				AddHWDescSequence(qid, &desc);
#ifdef DX_CONFIG_HW_RESET_CONST_SUPPORT
				HW_DESC_INIT(&desc);
				HW_DESC_RESET_CONST_INPUT(&desc);
				AddHWDescSequence(qid, &desc);
#endif
				/* get mac result */
				StoreCipherState(qid, pCtx);
			}
		}
	}

EndWithErr:
	return drvRc;
}
Пример #8
0
/*!
 * This function is used to process block(s) of data using the AES machine.
 * 
 * \param pCtx A pointer to the AES context buffer in SRAM.
 * \param pDmaInputBuffer A structure which represents the DMA input buffer.
 * \param pDmaOutputBuffer A structure which represents the DMA output buffer.
 * 
 * \return int One of DX_SYM_* error codes defined in dx_error.h.
 */
int ProcessCipher(struct sep_ctx_cipher *pCtx, DmaBuffer_s *pDmaInputBuffer, DmaBuffer_s *pDmaOutputBuffer)
{
	uint8_t *pInputData = NULL, *pOutputData = NULL;
	uint32_t isNotLastDescriptor = 0;
	uint32_t DataInSize = 0, DataOutSize = 0;
	uint32_t flowMode;
	HwDesc_s desc;
	DmaMode_t dmaMode = NO_DMA;
	uint8_t inAxiNs = pDmaInputBuffer->axiNs;
	uint8_t outAxiNs = pDmaOutputBuffer->axiNs;
	SepCipherPrivateContext_s *pAesPrivateCtx = (SepCipherPrivateContext_s *)pCtx->reserved;
	int nMlliTables = pDmaInputBuffer->nTables;
	int qid = CURR_QUEUE_ID(); /* qid is stored in pxTaskTag field */
	int drvRc = DX_RET_OK;
	const int isInplaceOp = (pDmaInputBuffer->pData == pDmaOutputBuffer->pData ||
				ReadContextWord(&pCtx->mode) == SEP_CIPHER_CBC_MAC ||
				ReadContextWord(&pCtx->mode) == SEP_CIPHER_XCBC_MAC ||
				ReadContextWord(&pCtx->mode) == SEP_CIPHER_CMAC);



	if (ReadContextWord(&pCtx->mode) == SEP_CIPHER_XTS) {
		/* in XTS the key must be loaded first */
		LoadCipherKey(qid, pCtx);
	 	LoadCipherState(qid, pCtx,0);
 	} else if(ReadContextWord(&pCtx->mode) == SEP_CIPHER_CBC_CTS){
		WriteContextWord(&pCtx->mode,SEP_CIPHER_CBC);
	 	LoadCipherState(qid, pCtx,0);
		LoadCipherKey(qid, pCtx);
		WriteContextWord(&pCtx->mode,SEP_CIPHER_CBC_CTS);
	} else {
		LoadCipherState(qid, pCtx,0);
		LoadCipherKey(qid, pCtx);
	}

	/* set the input/output pointers according to the DMA mode */
	if ((!isInplaceOp) && pDmaInputBuffer->dmaBufType != pDmaOutputBuffer->dmaBufType) {
		DX_PAL_LOG_ERR("Inconsistent DMA mode for in/out buffers");
		drvRc = DX_RET_INVARG;
		goto EndWithErr;
	}

	dmaMode = DMA_BUF_TYPE_TO_MODE(pDmaInputBuffer->dmaBufType);

	switch (dmaMode) {
	case DMA_MLLI:	
		pInputData = (uint8_t *)GetFirstLliPtr(qid, MLLI_INPUT_TABLE);
		PrepareFirstMLLITable(qid, pDmaInputBuffer, MLLI_INPUT_TABLE);

		/* get OUT MLLI tables pointer in SRAM (if not inplace operation) */
		if (isInplaceOp == 0) {
			pOutputData = (uint8_t *)GetFirstLliPtr(qid, MLLI_OUTPUT_TABLE);
			PrepareFirstMLLITable(qid, pDmaOutputBuffer, MLLI_OUTPUT_TABLE);
		} else {
			pOutputData = pInputData;
		}

		/* data size is meaningless in DMA-MLLI mode */
		DataInSize = 0;
		DataOutSize = 0;

		break;
	case DMA_DLLI:
	case DMA_SRAM:
		pInputData = (uint8_t *)pDmaInputBuffer->pData;
		if (isInplaceOp == 0) {
			pOutputData  = (uint8_t *)pDmaOutputBuffer->pData;
		} else {
			pOutputData = pInputData;
		}

		/* data processing is done */
		nMlliTables = 0;

		/* set the data size */
		DataInSize = pDmaInputBuffer->size;
		DataOutSize = pDmaOutputBuffer->size; 

		break;
	case DMA_MODE_NULL:
		pInputData = 0;
		pOutputData = 0;

		/* data processing is done */
		nMlliTables = 0;

		/* data size is meaningless in DMA-MLLI mode */
		DataInSize = 0;
		DataOutSize = 0;

		break;
	default:
		DX_PAL_LOG_ERR("Invalid DMA mode\n");
		drvRc = DX_RET_INVARG;
		goto EndWithErr;
	}

	if ((ReadContextWord(&pCtx->mode) == SEP_CIPHER_CMAC) || (ReadContextWord(&pCtx->mode) == SEP_CIPHER_XCBC_MAC)) {
		isNotLastDescriptor = 1; 
	}

	/* process the AES flow */
	HW_DESC_INIT(&desc);
	
	HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pInputData, DataInSize, QID_TO_AXI_ID(qid), inAxiNs);
	if (isNotLastDescriptor) {
		HW_DESC_SET_DIN_NOT_LAST_INDICATION(&desc);
	}

	switch (ReadContextWord(&pCtx->mode)) {
	case SEP_CIPHER_CBC_MAC:
	case SEP_CIPHER_CMAC:
	case SEP_CIPHER_XCBC_MAC:
		break;
	default:
		HW_DESC_SET_DOUT_TYPE(&desc, dmaMode, (uint32_t)pOutputData, DataOutSize, QID_TO_AXI_ID(qid), outAxiNs);
	}

	flowMode = (ReadContextWord(&pCtx->alg) == SEP_CRYPTO_ALG_AES) ? DIN_AES_DOUT : DIN_DES_DOUT;

	HW_DESC_SET_FLOW_MODE(&desc, flowMode);

#ifdef SEP_PERFORMANCE_TEST
	/* For testing exact HW time */
	HW_QUEUE_WAIT_UNTIL_EMPTY(qid);
	TIMING_MARK(1);
	TIMING_MARK(2);
#endif
	AddHWDescSequence(qid, &desc);
	
#ifdef SEP_PERFORMANCE_TEST
	TIMING_MARK(2);
	HW_QUEUE_WAIT_UNTIL_EMPTY(qid);
	TIMING_MARK(1);
#endif

	/* process each MLLI table (MLLI processing loop only) */
	while (--nMlliTables > 0) {
		/* prepare next input MLLI table in SRAM */
		PrepareNextMLLITable(qid, inAxiNs, MLLI_INPUT_TABLE);
		
		/* prepare next output MLLI table in SRAM */
		if (isInplaceOp == 0) {
			PrepareNextMLLITable(qid, outAxiNs, MLLI_OUTPUT_TABLE);
		}
		
		/* process the AES flow */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc, DMA_MLLI, (uint32_t)pInputData, 0, QID_TO_AXI_ID(qid), inAxiNs);
		if (isNotLastDescriptor) {
			HW_DESC_SET_DIN_NOT_LAST_INDICATION(&desc);
		}

		switch (ReadContextWord(&pCtx->mode)) {
		case SEP_CIPHER_CMAC:
		case SEP_CIPHER_CBC_MAC:
		case SEP_CIPHER_XCBC_MAC:
			break;
		default:
			HW_DESC_SET_DOUT_TYPE(&desc, DMA_MLLI, (uint32_t)pOutputData, 0, QID_TO_AXI_ID(qid), outAxiNs);
		}
		HW_DESC_SET_FLOW_MODE(&desc, flowMode);

		AddHWDescSequence(qid, &desc);
	}

	/* at least one block of data processed */
	WriteContextWord(&pAesPrivateCtx->isDataBlockProcessed,1);

	/* get machine state */
	StoreCipherState(qid, pCtx);

EndWithErr:
	return drvRc;
}
Пример #9
0
/*!
 * This function is used as finish operation of the HASH machine.
 * The function may either be called after "InitHash" or "ProcessHash".
 * 
 * \param pCtx A pointer to the AES context buffer in SRAM.
 * \param pDmaInputBuffer A structure which represents the DMA input buffer.
 * \param pDmaOutputBuffer A structure which represents the DMA output buffer.
 * 
 * \return int One of DX_SYM_* error codes defined in dx_error.h.
 */
int FinalizeHash(struct sep_ctx_hash *pCtx, DmaBuffer_s *pDmaInputBuffer, DmaBuffer_s *pDmaOutputBuffer)
{
	HwDesc_s desc;
	uint32_t isRemainingData = 0;
	uint32_t DataInSize = 0;
	DmaMode_t dmaMode = NO_DMA;
	uint8_t *pInputData = NULL;
	uint32_t hw_mode;

	uint32_t DigestSize;
	uint8_t inAxiNs = pDmaInputBuffer->axiNs;

	/* qid is stored in pxTaskTag field */
	int qid = CURR_QUEUE_ID();
	int drvRc = DX_RET_OK;

	HW_DESC_INIT(&desc);

	drvRc = GetHashHwMode(ReadContextWord(&pCtx->mode), &hw_mode);
	if (drvRc != DX_RET_OK) {
		return drvRc; 
	}

	/* SHA224 uses SHA256 HW mode with different init. val. */
	/*same for SHA384 with SHA512*/ 
	drvRc = GetHashHwDigestSize(ReadContextWord(&pCtx->mode), &DigestSize);
	if (drvRc != DX_RET_OK) {
		goto EndWithErr; 
	}

	dmaMode = DMA_BUF_TYPE_TO_MODE(pDmaInputBuffer->dmaBufType);

	/* check if we have remaining data to process */
	switch (dmaMode) {
	case DMA_MLLI:
		isRemainingData = pDmaInputBuffer->nTables;
		DataInSize = 0;
		break;
	case DMA_DLLI:
	case DMA_SRAM:
		isRemainingData = (pDmaInputBuffer->size > 0) ? 1 : 0;
		DataInSize = pDmaInputBuffer->size;
		break;
	case DMA_MODE_NULL:
		break;
	default:
		DX_PAL_LOG_ERR("Invalid DMA mode\n");
		drvRc = DX_RET_INVARG;
		goto EndWithErr;
	}	

	/* check if there is a remainder */
	if (isRemainingData > 1) {
		/* this case only apply to DMA_MLLI mode! */
		pDmaInputBuffer->nTables--;
		ProcessHash(pCtx, pDmaInputBuffer, NULL);

		/* process the last MLLI table */
		PrepareNextMLLITable(qid, inAxiNs, MLLI_INPUT_TABLE);

		/* load hash length and digest */
		drvRc = LoadHashState(qid, pCtx, HASH_PADDING_ENABLED);
		if (drvRc != DX_RET_OK) {
			goto EndWithErr; 
		}

		/* get the pointer of the input MLLI in SRAM */
		pInputData = (uint8_t *)GetFirstLliPtr(qid, MLLI_INPUT_TABLE);

		/* clobber remaining HASH data */
		HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pInputData, 0, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, DIN_HASH);
		AddHWDescSequence(qid, &desc);
	} else if (isRemainingData == 1) {
		/* load hash length and digest */
		drvRc = LoadHashState(qid, pCtx, HASH_PADDING_ENABLED);
		if (drvRc != DX_RET_OK) {
			goto EndWithErr; 
		}

		/* we have a single MLLI table */
		if (dmaMode == DMA_MLLI) {
			pInputData = (uint8_t *)GetFirstLliPtr(qid, MLLI_INPUT_TABLE);
			PrepareFirstMLLITable(qid, pDmaInputBuffer, MLLI_INPUT_TABLE);
		} else {
			pInputData = (uint8_t *)pDmaInputBuffer->pData;

			//* check sram!
		}

		/* clobber remaining HASH data */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pInputData, DataInSize, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, DIN_HASH);
		AddHWDescSequence(qid, &desc);
	} else {
		/* (isRemainingData == 0) */

		SepHashPrivateContext_s *PrivateContext = (SepHashPrivateContext_s *)pCtx;
		/* load hash length and digest */
		drvRc = LoadHashState(qid, pCtx, HASH_PADDING_DISABLED);
		if (drvRc != DX_RET_OK) {
			goto EndWithErr; 
		}

		/* Workaround: do-pad must be enabled only when writing current length to HW */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_CIPHER_MODE(&desc, hw_mode);
		HW_DESC_SET_CIPHER_CONFIG1(&desc, HASH_PADDING_DISABLED);
		HW_DESC_SET_CIPHER_DO(&desc, DO_PAD);
		HW_DESC_SET_STATE_DOUT_PARAM(&desc, (uint32_t)PrivateContext->CurrentDigestedLength,
				sizeof(PrivateContext->CurrentDigestedLength));
		HW_DESC_SET_FLOW_MODE(&desc, S_HASH_to_DOUT);
		HW_DESC_SET_SETUP_MODE(&desc, SETUP_WRITE_STATE1);
		AddHWDescSequence(qid, &desc);
	}



	/* store the hash digest result in the context */
	HW_DESC_INIT(&desc);
	HW_DESC_SET_CIPHER_MODE(&desc, hw_mode);

	HW_DESC_SET_STATE_DOUT_PARAM(&desc, (uint32_t)pCtx->digest, DigestSize);
	HW_DESC_SET_CIPHER_CONFIG0(&desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN);
	HW_DESC_SET_CIPHER_CONFIG1(&desc, HASH_PADDING_DISABLED);
	HW_DESC_SET_CIPHER_DO(&desc, DO_NOT_PAD);
	HW_DESC_SET_FLOW_MODE(&desc, S_HASH_to_DOUT);
	HW_DESC_SET_SETUP_MODE(&desc, SETUP_WRITE_STATE0);
	AddHWDescSequence(qid, &desc);
#ifdef DX_CONFIG_HASH_SHA_512_SUPPORTED
{
	uint32_t tempUint,i;
	if ((ReadContextWord(&pCtx->mode) == SEP_HASH_SHA512 || (ReadContextWord(&pCtx->mode) == SEP_HASH_SHA384))){
		WaitForSequenceCompletion();
		for( i = 0 ; i < DigestSize/sizeof(uint32_t); i++ )
		{
			if(i%2){

				tempUint = ReadContextWord(&((uint32_t*)(pCtx->digest))[i - 1]);
				WriteContextWord(&((uint32_t*)(pCtx->digest))[i - 1],ReadContextWord(&((uint32_t*)(pCtx->digest))[i]));
				WriteContextWord(&((uint32_t*)(pCtx->digest))[i],tempUint);
			}
		}

	}
}
#endif


EndWithErr:
	return drvRc;
}
Пример #10
0
/*!
 * This function is used to process a block(s) of data on HASH machine.
 * It accepts an input data aligned to hash block size, any reminder which is not
 * aligned should be passed on calling to "FinalizeHash".
 * 
 * \param pCtx A pointer to the AES context buffer in SRAM.
 * \param pDmaInputBuffer A structure which represents the DMA input buffer.
 * \param pDmaOutputBuffer A structure which represents the DMA output buffer.
 * 
 * \return int One of DX_SYM_* error codes defined in dx_error.h.
 */
int ProcessHash(struct sep_ctx_hash *pCtx, DmaBuffer_s *pDmaInputBuffer, DmaBuffer_s *pDmaOutputBuffer)
{
	uint8_t *pInputData = NULL;
	HwDesc_s desc;
	uint32_t DataInSize = 0;
	DmaMode_t dmaMode = NO_DMA;
	int nMlliTables = pDmaInputBuffer->nTables;
	uint8_t inAxiNs = pDmaInputBuffer->axiNs;
	int qid = CURR_QUEUE_ID(); /* qid is stored in pxTaskTag field */
	int drvRc = DX_RET_OK;


	HW_DESC_INIT(&desc);

	/* load hash length and digest */
	drvRc = LoadHashState(qid, pCtx, HASH_PADDING_DISABLED);
	if (drvRc != DX_RET_OK) {
		goto EndWithErr; 
	}

	dmaMode = DMA_BUF_TYPE_TO_MODE(pDmaInputBuffer->dmaBufType);

	/* set the input pointer according to the DMA mode */
	switch (dmaMode) {
	case DMA_MLLI:
		pInputData = (uint8_t *)GetFirstLliPtr(qid, MLLI_INPUT_TABLE);
		PrepareFirstMLLITable(qid, pDmaInputBuffer, MLLI_INPUT_TABLE);

		/* data size is meaningless in DMA-MLLI mode */
		DataInSize = 0;

		break;
	case DMA_DLLI:
	case DMA_SRAM:
		pInputData = (uint8_t *)pDmaInputBuffer->pData;

		/* data processing is done */
		nMlliTables = 0;

		/* set the data size */
		DataInSize = pDmaInputBuffer->size;

		break;
	default:
		DX_PAL_LOG_ERR("Invalid DMA mode\n");
		drvRc = DX_RET_INVARG;
		goto EndWithErr;
	}

	/* process the HASH flow */
	HW_DESC_SET_DIN_TYPE(&desc, dmaMode, (uint32_t)pInputData, DataInSize, QID_TO_AXI_ID(qid), inAxiNs);
	HW_DESC_SET_FLOW_MODE(&desc, DIN_HASH);
	AddHWDescSequence(qid, &desc);

	/* process the rest of MLLI tables (MLLI processing loop only) */
	while (--nMlliTables > 0) {

		/* prepare next input MLLI table in SRAM */
		PrepareNextMLLITable(qid, inAxiNs, MLLI_INPUT_TABLE);

		/* process the HASH flow */
		HW_DESC_INIT(&desc);
		HW_DESC_SET_DIN_TYPE(&desc, DMA_MLLI, (uint32_t)pInputData, 0, QID_TO_AXI_ID(qid), inAxiNs);
		HW_DESC_SET_FLOW_MODE(&desc, DIN_HASH);
		AddHWDescSequence(qid, &desc);
	}

	/* write back digest and hash length */
	StoreHashState(qid, pCtx);

EndWithErr:
	return drvRc;
}