/*! * 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); }
/*! * This function is used to initialize the HASH machine to perform the * HASH 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 InitHash(struct sep_ctx_hash *pCtx) { SepHashPrivateContext_s *PrivateContext = (SepHashPrivateContext_s *)pCtx; /* copy the hash initial digest to the user context */ switch(ReadContextWord(&pCtx->mode)) { case SEP_HASH_SHA1: WriteContextField(pCtx->digest, gLarvalSha1Digest, SEP_SHA1_DIGEST_SIZE); break; case SEP_HASH_SHA224: WriteContextField(pCtx->digest, gLarvalSha224Digest, SEP_SHA256_DIGEST_SIZE); break; case SEP_HASH_SHA256: WriteContextField(pCtx->digest, gLarvalSha256Digest, SEP_SHA256_DIGEST_SIZE); break; #ifdef DX_CONFIG_HASH_SHA_512_SUPPORTED case SEP_HASH_SHA384: WriteContextField(pCtx->digest, gLarvalSha384Digest, SEP_SHA512_DIGEST_SIZE); break; case SEP_HASH_SHA512: WriteContextField(pCtx->digest, gLarvalSha512Digest, SEP_SHA512_DIGEST_SIZE); break; #endif default: DX_PAL_LOG_ERR("Unsupported hash mode %d\n", ReadContextWord(&pCtx->mode)); return DX_RET_UNSUPP_ALG_MODE; } /* clear hash length and load it to the hash machine -we're starting a new transaction */ ClearCtxField(PrivateContext->CurrentDigestedLength, sizeof(PrivateContext->CurrentDigestedLength)); WriteContextWord(&PrivateContext->dataCompleted,0); WriteContextWord(&PrivateContext->hmacFinalization,0); return DX_RET_OK; }
/*! * 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; }
/*! * Revert operation of the last MAC block processing * This function is used for AES-XCBC-MAC and AES-CMAC when finalize * has not data. It reverts the last block operation in order to allow * redoing it as final. * * \param qid * \param pCtx * * \return int One of DX_SYM_* error codes defined in dx_error.h. */ static int RevertLastMacBlock(int qid, struct sep_ctx_cipher *pCtx) { HwDesc_s desc; XcbcMacRfcKeys_s *XcbcKeys = (XcbcMacRfcKeys_s*)pCtx->key; /* Relevant only for AES-CMAC and AES-XCBC-MAC */ if ((ReadContextWord(&pCtx->mode) != SEP_CIPHER_XCBC_MAC) && (ReadContextWord(&pCtx->mode) != SEP_CIPHER_CMAC)) { DX_PAL_LOG_ERR("Wrong mode for this function (mode %d)\n", ReadContextWord(&pCtx->mode)); return DX_RET_UNSUPP_ALG_MODE; } if (ReadContextWord(&pCtx->crypto_key_type) == DX_ROOT_KEY) { DX_PAL_LOG_ERR("RKEK not allowed for XCBC-MAC/CMAC\n"); return DX_RET_UNSUPP_ALG_MODE; } /* CMAC and XCBC must use 128b keys */ if ((ReadContextWord(&pCtx->mode) == SEP_CIPHER_XCBC_MAC) && (ReadContextWord(&pCtx->key_size) != SEP_AES_128_BIT_KEY_SIZE)) { DX_PAL_LOG_ERR("Bad key for XCBC-MAC %x\n", (unsigned int)ReadContextWord(&pCtx->key_size)); return DX_RET_INVARG_KEY_SIZE; } /* Load key for ECB decryption */ HW_DESC_INIT(&desc); HW_DESC_SET_CIPHER_MODE(&desc, SEP_CIPHER_ECB); HW_DESC_SET_CIPHER_CONFIG0(&desc, SEP_CRYPTO_DIRECTION_DECRYPT); if (ReadContextWord(&pCtx->mode) == SEP_CIPHER_XCBC_MAC) { /* XCBC K1 key is used (always 128b) */ HW_DESC_SET_STATE_DIN_PARAM(&desc, (uint32_t)XcbcKeys->K1, SEP_AES_128_BIT_KEY_SIZE); HW_DESC_SET_KEY_SIZE_AES(&desc, SEP_AES_128_BIT_KEY_SIZE); } else {/* CMAC */ HW_DESC_SET_STATE_DIN_PARAM(&desc, (uint32_t)pCtx->key, (ReadContextWord(&pCtx->key_size) == 24) ? SEP_AES_KEY_SIZE_MAX : ReadContextWord(&pCtx->key_size)); HW_DESC_SET_KEY_SIZE_AES(&desc, ReadContextWord(&pCtx->key_size)); } HW_DESC_SET_FLOW_MODE(&desc, S_DIN_to_AES); HW_DESC_SET_SETUP_MODE(&desc, SETUP_LOAD_KEY0); AddHWDescSequence(qid, &desc); /* Initiate decryption of block state to previous block_state-XOR-M[n] */ HW_DESC_INIT(&desc); HW_DESC_SET_STATE_DIN_PARAM(&desc, (uint32_t)pCtx->block_state, SEP_AES_BLOCK_SIZE); HW_DESC_SET_STATE_DOUT_PARAM(&desc, (uint32_t)pCtx->block_state, SEP_AES_BLOCK_SIZE); HW_DESC_SET_FLOW_MODE(&desc, DIN_AES_DOUT); AddHWDescSequence(qid, &desc); return DX_RET_OK; }
/*! * Get Hash digest size in bytes. * * \param mode Hash mode * \param digestSize [out] A pointer to the digest size return value * * \return int One of DX_SYM_* error codes defined in dx_error.h. */ int GetHashDigestSize(const enum sep_hash_mode mode, uint32_t *digestSize) { if (mode >= SEP_HASH_MODE_NUM) { DX_PAL_LOG_ERR("Unsupported hash mode"); *digestSize = 0; return DX_RET_UNSUPP_ALG_MODE; } *digestSize = gHashDigestSize[mode]; return DX_RET_OK; }
/*! * Translate Hash mode to hardware specific Hash mode. * * \param mode Hash mode * \param hwMode [out] A pointer to the hash mode return value * * \return int One of DX_SYM_* error codes defined in dx_error.h. */ int GetHashHwMode(const enum sep_hash_mode mode, uint32_t *hwMode) { if (mode >= SEP_HASH_MODE_NUM) { DX_PAL_LOG_ERR("Unsupported hash mode"); *hwMode = SEP_HASH_NULL; return DX_RET_UNSUPP_ALG_MODE; } *hwMode = gHashHwMode[mode]; return DX_RET_OK; }
/*! * Get Hash block Size length in bytes. * * \param mode Hash mode * * \return int digest size return value. */ static int GetHmacBlocktSize(const enum sep_hash_mode mode) { if (mode >= SEP_HASH_MODE_NUM) { DX_PAL_LOG_ERR("Unsupported hash mode"); return 0; } if (mode <= SEP_HASH_SHA224) return CRYS_HASH_BLOCK_SIZE_IN_BYTES; else return CRYS_HASH_SHA512_BLOCK_SIZE_IN_BYTES; }
/*! * Get Hash block size in bytes. * * \param mode Hash mode * \param blockSize [out] A pointer to the hash block size return value * * \return int One of DX_SYM_* error codes defined in dx_error.h. */ int GetHashBlockSize(const enum sep_hash_mode mode, uint32_t *blockSize) { if (mode >= SEP_HASH_MODE_NUM) { DX_PAL_LOG_ERR("Unsupported hash mode"); *blockSize = 0; return DX_RET_UNSUPP_ALG_MODE; } if (mode <= SEP_HASH_SHA224) *blockSize = SEP_SHA1_224_256_BLOCK_SIZE; else *blockSize = SEP_SHA512_BLOCK_SIZE; return DX_RET_OK; }
/*! * 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; }
/*! * 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; }
/*! * Memory copy using HW engines * * reserved [unused] * pDmaInputBuffer [in] -A structure which represents the DMA input buffer. * pDmaOutputBuffer [in/out] -A structure which represents the DMA output buffer. * * \return int One of DX_SYM_* error codes defined in dx_error.h. */ int ProcessBypass(struct sep_ctx_generic *reserved, DmaBuffer_s *pDmaInputBuffer, DmaBuffer_s *pDmaOutputBuffer) { Bypass_t dmaTypeIn, dmaTypeOut; int drvRc = DX_RET_OK; dmaTypeIn = GetBypassType(pDmaInputBuffer->dmaBufType, pDmaInputBuffer->pData); dmaTypeOut = GetBypassType(pDmaOutputBuffer->dmaBufType, pDmaOutputBuffer->pData); if ((dmaTypeIn == BYPASS_MAX) || (dmaTypeOut == BYPASS_MAX)) { DX_PAL_LOG_ERR("Invalid din/dout memory type\n"); drvRc = DX_RET_INVARG; goto EndWithErr; } switch (dmaTypeIn) { case BYPASS_SRAM: switch (dmaTypeOut) { case BYPASS_DLLI: if (IS_ALIGNED(pDmaInputBuffer->pData, sizeof(uint32_t)) || IS_MULT(pDmaInputBuffer->size, sizeof(uint32_t))) { DescBypass( DMA_SRAM, pDmaInputBuffer->pData, pDmaInputBuffer->size, pDmaInputBuffer->axiNs, DMA_DLLI, pDmaOutputBuffer->pData, pDmaOutputBuffer->size, pDmaOutputBuffer->axiNs); } else { DX_PAL_LOG_ERR("Bad address or bad size. SRAM to DLLI copy -Input address %xl with %ul B\n", pDmaInputBuffer->pData, pDmaInputBuffer->size); drvRc = DX_RET_INVARG; goto EndWithErr; } break; default: DX_PAL_LOG_ERR("Invalid BYPASS mode\n"); drvRc = DX_RET_UNSUPP_ALG_MODE; goto EndWithErr; } break; case BYPASS_DLLI: switch (dmaTypeOut) { case BYPASS_SRAM: if (IS_ALIGNED(pDmaInputBuffer->pData, sizeof(uint32_t)) || IS_MULT(pDmaInputBuffer->size, sizeof(uint32_t))) { DescBypass( DMA_DLLI, pDmaInputBuffer->pData, pDmaInputBuffer->size, pDmaInputBuffer->axiNs, DMA_SRAM, pDmaOutputBuffer->pData, pDmaOutputBuffer->size, pDmaOutputBuffer->axiNs); } else { DX_PAL_LOG_ERR("Bad address or bad size. SRAM to DLLI copy -Input address %xl with %ul B\n", pDmaInputBuffer->pData, pDmaInputBuffer->size); drvRc = DX_RET_INVARG; goto EndWithErr; } break; case BYPASS_DLLI: DescBypass( DMA_BUF_TYPE_TO_MODE(pDmaInputBuffer->dmaBufType), pDmaInputBuffer->pData, pDmaInputBuffer->size, pDmaInputBuffer->axiNs, DMA_BUF_TYPE_TO_MODE(pDmaOutputBuffer->dmaBufType), pDmaOutputBuffer->pData, pDmaOutputBuffer->size, pDmaOutputBuffer->axiNs); break; default: DX_PAL_LOG_ERR("Invalid BYPASS mode\n"); drvRc = DX_RET_UNSUPP_ALG_MODE; goto EndWithErr; } break; default: DX_PAL_LOG_ERR("Invalid BYPASS mode\n"); drvRc = DX_RET_UNSUPP_ALG_MODE; break; } EndWithErr: return drvRc; }