Esempio n. 1
0
/*!
 * This function initiates reading of MLLI table in given host memory to
 * the MLLI buffer in SRAM. It pushes DLLI-to-SRAM BYPASS descriptor.
 *
 * \param qid [in] -The queue Id.
 * \param mlliHostAddr [in] - Host DMA address of a structure which represents the 
 *			MLLI table as follow:
 *		     1. A pointer to the first input MLLI table in system RAM
 *		     	and it's size.
 *		     2. The total number of MLLI tables.
 *		     3. The table direction (can be either MLLI_INPUT_TABLE or
 *		     	MLLI_OUTPUT_TABLE).
 * \param tableSize The size in bytes of the pointed MLLI table.
 * \param axiNs The AXI NS bit
 * \param direction Denotes whether this is MLLI for input or for output
*/
void FetchMlliTable(int qid, uint32_t pMlliData, uint32_t size, uint8_t axiNs, MLLIDirection_t direction)
{
	uint32_t mlliAdr;
	HwDesc_s desc;

	/* Check if already allocated by external module */
	if ( DX_GetIsMlliExternalAlloc(qid) == 1 ) {
		DX_PAL_Abort("MLLI workspace is already allocated by external module");
	}
	
	if (size > (MLLI_BUF_SIZE - SEP_LLI_ENTRY_BYTE_SIZE)) {
		DX_PAL_LOG_ERR("Given MLLI size=%u B is too large!\n", (unsigned int)size);
		DX_PAL_Abort("Given MLLI size is too large!");
	}

	mlliAdr = (uint32_t)(DX_GetMLLIWorkspace() + qid * MLLI_IN_OUT_BUF_SIZE);
	mlliAdr += ( direction == MLLI_INPUT_TABLE ? 0 : MLLI_BUF_SIZE );

	/* prepare the first MLLI mlliTable from host */
	HW_DESC_INIT(&desc);
	HW_DESC_SET_DIN_TYPE(&desc, DMA_DLLI, pMlliData, size, QID_TO_AXI_ID(qid), axiNs);
	HW_DESC_SET_DOUT_SRAM(&desc, mlliAdr, size);
	HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
	AddHWDescSequence(qid, &desc);
}
/*!
 * Generates the initial pool in SRAM.
 * This function should be invoked when resuming DX driver.
 *
 * \param drvdata
 *
 * \return int Zero for success, negative value otherwise.
 */
int dx_ivgen_init_sram_pool(struct dx_drvdata *drvdata)
{
	struct dx_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
	HwDesc_s iv_seq[DX_IVPOOL_SEQ_LEN];
	struct dx_crypto_req dx_req = {0};
	unsigned int iv_seq_len = 0;

	/* Generate initial enc. key/iv */
	get_random_bytes(ivgen_ctx->pool_meta, DX_IVPOOL_META_SIZE);

	/* The first 32B reserved for the enc. Key/IV */
	ivgen_ctx->ctr_key = ivgen_ctx->pool;
	ivgen_ctx->ctr_iv = ivgen_ctx->pool + AES_KEYSIZE_128;

	/* Copy initial enc. key and IV to SRAM at a single descriptor */
	HW_DESC_INIT(&iv_seq[iv_seq_len]);
	HW_DESC_SET_DIN_TYPE(&iv_seq[iv_seq_len], DMA_DLLI,
		ivgen_ctx->pool_meta_dma, DX_IVPOOL_META_SIZE,
		AXI_ID, NS_BIT);
	HW_DESC_SET_DOUT_SRAM(&iv_seq[iv_seq_len], ivgen_ctx->pool,
		DX_IVPOOL_META_SIZE);
	HW_DESC_SET_FLOW_MODE(&iv_seq[iv_seq_len], BYPASS);
	iv_seq_len++;

	/* Generate initial pool */
	dx_ivgen_generate_pool(ivgen_ctx, iv_seq, &iv_seq_len);

	/* Fire-and-forget */
	return send_request(drvdata, &dx_req, iv_seq, iv_seq_len, 0);
}
Esempio n. 3
0
/*!
 * Copy data buffer indirectly using CC HW descriptors.
 * 
 * \param inType DMA type of the source buffer.
 * \param inAddr Input address of the source buffer, must be word aligned.
 * \param inSize Size in octets of the source buffer, must be multiple of word.
 * \param inAxiNs The AXI bus secure mode of the source buffer.
 * \param outType DMA type of the source buffer.
 * \param outAddr Output address of the destination buffer, must be word aligned.
 * \param outSize Size in octets of the destination buffer, must be multiple of word.
 * \param outAxiNs The AXI bus secure mode of the destination buffer.
 */
static void DescBypass(
	DmaMode_t inType, 
	uint32_t  inAddr, 
	uint32_t inSize,
	uint32_t inAxiNs,
	DmaMode_t outType, 
	uint32_t outAddr,
	uint32_t outSize,
	uint32_t outAxiNs )
{
	HwDesc_s desc;
	
	/* Execute BYPASS operation */
	HW_DESC_INIT(&desc);
	HW_DESC_SET_DIN_TYPE(&desc, inType, inAddr, inSize, QID_TO_AXI_ID(NO_OS_QUEUE_ID), inAxiNs);
	HW_DESC_SET_DOUT_TYPE(&desc, outType, outAddr, outSize, QID_TO_AXI_ID(NO_OS_QUEUE_ID), outAxiNs);
	HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
	AddHWDescSequence(NO_OS_QUEUE_ID, &desc);
}
Esempio n. 4
0
/*!
 * This function prepares the next MLLI table. It looks for the source
 * address and size of the next LLI table in the first entry of the
 * populated MLLI table in SRAM and overwrites it in the SRAM using
 * "MLLI" transfer.
 *
 * \param qid [in] - The queue Id.
 * \param axiNs [in] - axi secure transactions
 * \param dir [in] - Refers to INPUT or OUTPUT MLLI table in SeP RAM.
 */
void PrepareNextMLLITable(int qid, uint8_t axiNs, MLLIDirection_t direction)
{
	uint32_t mlliAdr;
	HwDesc_s desc;

	/* Check if already allocated by external module */
	if ( DX_GetIsMlliExternalAlloc(qid) == 1 ) {
		DX_PAL_Abort("MLLI workspace is already allocated by external module");
	}
	
	mlliAdr = (uint32_t)(DX_GetMLLIWorkspace() + qid * MLLI_IN_OUT_BUF_SIZE);
	mlliAdr += ( direction == MLLI_INPUT_TABLE ? 0 : MLLI_BUF_SIZE );
	
	/* prepare the next MLLI table. The next table host address already
	   resides in SRAM and needs to be transfered to the same address
	   in SRAM */
	HW_DESC_INIT(&desc);
	HW_DESC_SET_DIN_TYPE(&desc, DMA_MLLI, mlliAdr, 0, QID_TO_AXI_ID(qid), axiNs);
	HW_DESC_SET_DOUT_SRAM(&desc, mlliAdr, MLLI_BUF_SIZE - SEP_LLI_ENTRY_BYTE_SIZE);
	HW_DESC_SET_FLOW_MODE(&desc, BYPASS);
	AddHWDescSequence(qid, &desc);
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}
Esempio n. 7
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;
}
Esempio n. 8
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;
}
Esempio n. 9
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;
}