/****************************************************************************** * * This function calculates the next block size and updates the required * parameters. * * @param PartitionParams is a pointer to XFsblPs_PlPartition * @param ChunkAdrs is a pointer to the data location * @param ChunkSize is the remaining chunk size * * @return * Error code on failure * XFSBL_SUCESS on success * * @note None * ******************************************************************************/ static u32 XFsbl_DecrptSetUpNextBlk(XFsblPs_PlPartition *PartitionParams, UINTPTR ChunkAdrs, u32 ChunkSize) { u32 Status = XFSBL_SUCCESS; u32 SssAes; u32 SssCfg; /* Length of next block */ PartitionParams->PlEncrypt.NextBlkLen = Xil_Htonl(XSecure_ReadReg( PartitionParams->PlEncrypt.SecureAes->BaseAddress, XSECURE_CSU_AES_IV_3_OFFSET)) * 4; PartitionParams->PlEncrypt.SecureAes->Iv = (u32 *)(PartitionParams->PlEncrypt.SecureAes->BaseAddress + (UINTPTR)XSECURE_CSU_AES_IV_0_OFFSET); /* Configure the SSS for AES. */ SssAes = XSecure_SssInputAes(XSECURE_CSU_SSS_SRC_SRC_DMA); SssCfg = SssAes | XSecure_SssInputPcap(XSECURE_CSU_SSS_SRC_AES); XSecure_SssSetup(SssCfg); /* Start the message. */ XSecure_WriteReg(PartitionParams->PlEncrypt.SecureAes->BaseAddress, XSECURE_CSU_AES_START_MSG_OFFSET, XSECURE_CSU_AES_START_MSG); /* Transfer IV of the next block */ XFsbl_DmaPlCopy(PartitionParams->PlEncrypt.SecureAes->CsuDmaPtr, (UINTPTR)PartitionParams->PlEncrypt.SecureAes->Iv, XSECURE_SECURE_GCM_TAG_SIZE/4, 0); PartitionParams->PlEncrypt.SecureAes->SizeofData = PartitionParams->PlEncrypt.NextBlkLen; XSecure_WriteReg(PartitionParams->PlEncrypt.SecureAes->BaseAddress, XSECURE_CSU_AES_KUP_WR_OFFSET, 0x0); return Status; }
/** * * Configure SSS and start the SHA-3 engine * * @param InstancePtr is a pointer to the XSecure_Sha3 instance. * * @return None * * @note None * ******************************************************************************/ void XSecure_Sha3Start(XSecure_Sha3 *InstancePtr) { /* Asserts validate the input arguments */ Xil_AssertVoid(InstancePtr != NULL); InstancePtr->Sha3Len = 0U; /* Reset SHA3 engine. */ XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_SHA3_RESET_OFFSET, XSECURE_CSU_SHA3_RESET_RESET); XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_SHA3_RESET_OFFSET, 0U); /* Configure the SSS for SHA3 hashing. */ XSecure_SssSetup(XSecure_SssInputSha3(XSECURE_CSU_SSS_SRC_SRC_DMA)); /* Start SHA3 engine. */ XSecure_WriteReg(InstancePtr->BaseAddress, XSECURE_CSU_SHA3_START_OFFSET, XSECURE_CSU_SHA3_START_START); }
/****************************************************************************** * * This API decrypts the chunks of data * * @param PartitionParams is a pointer to XFsblPs_PlPartition * @param ChunkAdrs holds the address of chunk address * @param ChunkSize holds the size of chunk * * @return * Error code on failure * XFSBL_SUCESS on success * * @note None. * ******************************************************************************/ static u32 XFsbl_DecrptPlChunks(XFsblPs_PlPartition *PartitionParams, u64 ChunkAdrs, u32 ChunkSize) { u32 Status = XFSBL_SUCCESS; UINTPTR SrcAddr = (u64)ChunkAdrs; u32 Size = ChunkSize; u64 NextBlkAddr = 0; u32 SssAes; u32 SssCfg; /* If this is the first block to be decrypted it is the secure header */ if (PartitionParams->PlEncrypt.NextBlkLen == 0x00) { XSecure_AesDecryptInit(PartitionParams->PlEncrypt.SecureAes, (u8 *)XSECURE_DESTINATION_PCAP_ADDR, XSECURE_SECURE_HDR_SIZE, (u8 *)(SrcAddr + XSECURE_SECURE_HDR_SIZE)); /* * Configure AES engine to push decrypted Key and IV in the * block to the CSU KEY and IV registers. */ XSecure_WriteReg( PartitionParams->PlEncrypt.SecureAes->BaseAddress, XSECURE_CSU_AES_KUP_WR_OFFSET, XSECURE_CSU_AES_IV_WR | XSECURE_CSU_AES_KUP_WR); /* Decrypting the Secure header */ Status = XSecure_AesDecryptUpdate( PartitionParams->PlEncrypt.SecureAes, (u8 *)(SrcAddr), XSECURE_SECURE_HDR_SIZE); if (Status != XFSBL_SUCCESS) { XFsbl_Printf(DEBUG_GENERAL, "XFSBL_DECRYPT_SECURE_HEADER:" "XFSBL_ERROR_BITSTREAM_GCM_TAG_MISMATCH\r\n"); Status = XFSBL_ERROR_BITSTREAM_GCM_TAG_MISMATCH; goto END; } PartitionParams->PlEncrypt.SecureAes->KeySel = XSECURE_CSU_AES_KEY_SRC_KUP; XSecure_AesKeySelNLoad(PartitionParams->PlEncrypt.SecureAes); /* Point IV to the CSU IV register. */ PartitionParams->PlEncrypt.SecureAes->Iv = (u32 *)(PartitionParams->PlEncrypt.SecureAes->BaseAddress + (UINTPTR)XSECURE_CSU_AES_IV_0_OFFSET); /* * Remaining size and source address * of the data to be processed */ Size = ChunkSize - XSECURE_SECURE_HDR_SIZE - XSECURE_SECURE_GCM_TAG_SIZE; SrcAddr = ChunkAdrs + XSECURE_SECURE_HDR_SIZE+XSECURE_SECURE_GCM_TAG_SIZE; /* * Decrypt next block after Secure header and * update the required fields */ Status = XFsbl_DecrptSetUpNextBlk(PartitionParams, SrcAddr, Size); if (Status != XFSBL_SUCCESS) { goto END; } Status = XFsbl_DecrptPl(PartitionParams, (UINTPTR)SrcAddr, Size); if (Status != XFSBL_SUCCESS) { goto END; } /* * If status is true or false also goto END * As remaining data also processed in above API */ goto END; } /* * If previous chunk has portion of left header, * which needs to be processed along with this chunk */ else if (PartitionParams->Hdr != 0x00) { /* Configure AES engine */ SssAes = XSecure_SssInputAes(XSECURE_CSU_SSS_SRC_SRC_DMA); SssCfg = SssAes | XSecure_SssInputPcap(XSECURE_CSU_SSS_SRC_AES); XSecure_SssSetup(SssCfg); XFsbl_CopyData(PartitionParams, (u8 *)(PartitionParams->SecureHdr + PartitionParams->Hdr), (u8 *)(UINTPTR)SrcAddr, XFSBL_AES_TAG_SIZE - PartitionParams->Hdr); Status = XFsbl_DecrypSecureHdr( PartitionParams->PlEncrypt.SecureAes, (u64)(UINTPTR)PartitionParams->SecureHdr, 0); if (Status != XFSBL_SUCCESS) { return Status; } Size = Size - (XFSBL_AES_TAG_SIZE - PartitionParams->Hdr); if (Size != 0x00) { NextBlkAddr = SrcAddr + (XFSBL_AES_TAG_SIZE - PartitionParams->Hdr); } PartitionParams->Hdr = 0; memset(PartitionParams->SecureHdr, 0, XFSBL_AES_TAG_SIZE); /* * This means we are done with Secure header and Block 0 * And now we can change the AES key source to KUP. */ PartitionParams->PlEncrypt.SecureAes->KeySel = XSECURE_CSU_AES_KEY_SRC_KUP; XSecure_AesKeySelNLoad(PartitionParams->PlEncrypt.SecureAes); Status = XFsbl_DecrptSetUpNextBlk(PartitionParams, NextBlkAddr, Size); if (Status != XFSBL_SUCCESS) { return Status; } if ((NextBlkAddr != 0x00U) && (PartitionParams->PlEncrypt.SecureAes->SizeofData != 0)) { Status = XFsbl_DecrptPl(PartitionParams, (UINTPTR)NextBlkAddr, Size); if (Status != XFSBL_SUCCESS) { return Status; } } } else { Status = XFsbl_DecrptPl(PartitionParams, SrcAddr, Size); goto END; } END: return Status; }
/****************************************************************************** * * This function sends data to AES engine which needs to be decrypted till the * end of the encryption block. * * @param PartitionParams is a pointer to XFsblPs_PlPartition * @param ChunkAdrs is a pointer to the data location * @param ChunkSize is the remaining chunk size * * @return * Error code on failure * XFSBL_SUCESS on success * * @note None * ******************************************************************************/ static u32 XFsbl_DecrptPl(XFsblPs_PlPartition *PartitionParams, u64 ChunkAdrs, u32 ChunkSize) { u32 Size = ChunkSize; u32 Status = XFSBL_SUCCESS; u64 SrcAddr = (u64)ChunkAdrs; XCsuDma_Configure ConfigurValues = {0}; UINTPTR NextBlkAddr = 0; u32 SssAes; u32 SssCfg; do { /* Enable byte swapping */ XCsuDma_GetConfig( PartitionParams->PlEncrypt.SecureAes->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); ConfigurValues.EndianType = 1U; XCsuDma_SetConfig( PartitionParams->PlEncrypt.SecureAes->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); /* Configure AES engine */ SssAes = XSecure_SssInputAes(XSECURE_CSU_SSS_SRC_SRC_DMA); SssCfg = SssAes | XSecure_SssInputPcap(XSECURE_CSU_SSS_SRC_AES); XSecure_SssSetup(SssCfg); /* Send whole chunk of data to AES */ if ((Size <= (PartitionParams->PlEncrypt.SecureAes->SizeofData)) && (PartitionParams->PlEncrypt.SecureAes->SizeofData != 0)) { XFsbl_DmaPlCopy( PartitionParams->PlEncrypt.SecureAes->CsuDmaPtr, (UINTPTR)SrcAddr, Size/4, 0); PartitionParams->PlEncrypt.SecureAes->SizeofData = PartitionParams->PlEncrypt.SecureAes->SizeofData - Size; Size = 0; } /* * If data to be processed is not zero * and chunk of data is greater */ else if (PartitionParams->PlEncrypt.SecureAes->SizeofData != 0) { /* First transfer whole data other than secure header */ XFsbl_DmaPlCopy( PartitionParams->PlEncrypt.SecureAes->CsuDmaPtr, (UINTPTR)SrcAddr, PartitionParams->PlEncrypt.SecureAes->SizeofData/4, 0); SrcAddr = SrcAddr + PartitionParams->PlEncrypt.SecureAes->SizeofData; Size = Size - PartitionParams->PlEncrypt.SecureAes->SizeofData; PartitionParams->PlEncrypt.SecureAes->SizeofData = 0; /* * when data to be processed is greater than * remaining data of the encrypted block * and part of GCM tag and secure header of next block * also exists with chunk, copy that portion for * proceessing along with next chunk of data */ if (Size < (XSECURE_SECURE_HDR_SIZE + XSECURE_SECURE_GCM_TAG_SIZE)) { XFsbl_CopyData(PartitionParams, PartitionParams->SecureHdr, (u8 *)(UINTPTR)SrcAddr, Size); PartitionParams->Hdr = Size; Size = 0; } } /* Wait PCAP done */ Status = XFsbl_PcapWaitForDone(); if (Status != XFSBL_SUCCESS) { return Status; } XCsuDma_GetConfig( PartitionParams->PlEncrypt.SecureAes->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); ConfigurValues.EndianType = 0U; XCsuDma_SetConfig( PartitionParams->PlEncrypt.SecureAes->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); /* Decrypting secure header and GCM tag address */ if ((PartitionParams->PlEncrypt.SecureAes->SizeofData == 0) && (Size != 0)) { Status = XFsbl_DecrypSecureHdr( PartitionParams->PlEncrypt.SecureAes, SrcAddr, 0); if (Status != XFSBL_SUCCESS) { return Status; } Size = Size - (XSECURE_SECURE_HDR_SIZE + XSECURE_SECURE_GCM_TAG_SIZE); if (Size != 0x00) { NextBlkAddr = SrcAddr + XSECURE_SECURE_HDR_SIZE + XSECURE_SECURE_GCM_TAG_SIZE; } /* * This means we are done with Secure header and Block 0 * And now we can change the AES key source to KUP. */ PartitionParams->PlEncrypt.SecureAes->KeySel = XSECURE_CSU_AES_KEY_SRC_KUP; XSecure_AesKeySelNLoad( PartitionParams->PlEncrypt.SecureAes); Status = XFsbl_DecrptSetUpNextBlk(PartitionParams, NextBlkAddr, Size); if (Status != XFSBL_SUCCESS) { return Status; } if ((NextBlkAddr != 0x00U) && (PartitionParams->PlEncrypt.SecureAes->SizeofData != 0)) { SrcAddr = NextBlkAddr; } else { break; } } } while (Size != 0x00); return Status; }