/*! * 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"); }
/*! * 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; }
/*! * 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; }
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); }
/*! * 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; }
/*! * 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; }
/*! * 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; }
/*! * 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; }
/*! * 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; }
/*! * 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; }