Exemplo n.º 1
0
/** This is the function to write data to PCAP interface
 *
 * @param	WrSize: Number of 32bit words that the DMA should write to
 *          the PCAP interface
 * @param   WrAddr: Linear memory space from where CSUDMA will read
 *	        the data to be written to PCAP interface
 *
 * @return	None
 *
 *****************************************************************************/
u32 XFsbl_WriteToPcap(u32 WrSize, u8 *WrAddr) {
	u32 RegVal;
	u32 Status = XFSBL_SUCCESS;

	/*
	 * Setup the  SSS, setup the PCAP to receive from DMA source
	 */
	RegVal = XFsbl_In32(CSU_CSU_SSS_CFG) & CSU_CSU_SSS_CFG_PCAP_SSS_MASK;
	RegVal = RegVal
			| (XFSBL_CSU_SSS_SRC_SRC_DMA << CSU_CSU_SSS_CFG_PCAP_SSS_SHIFT);
	XFsbl_Out32(CSU_CSU_SSS_CFG, RegVal);

	/* Setup the source DMA channel */
	XCsuDma_Transfer(&CsuDma, XCSUDMA_SRC_CHANNEL, (PTRSIZE) WrAddr, WrSize, 0);

	/* wait for the SRC_DMA to complete and the pcap to be IDLE */
	XCsuDma_WaitForDone(&CsuDma, XCSUDMA_SRC_CHANNEL);

	/* Acknowledge the transfer has completed */
	XCsuDma_IntrClear(&CsuDma, XCSUDMA_SRC_CHANNEL, XCSUDMA_IXR_DONE_MASK);

	XFsbl_Printf(DEBUG_GENERAL, "DMA transfer done \r\n");
	Status = XFsbl_PcapWaitForDone();
	if (Status != XFSBL_SUCCESS) {
		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;

}
/******************************************************************************
*
* This function re-authenticates the each chunk of the block and compares
* with the stored hash and sends the data AES engine if encryption exists
* and to PCAP directly in encryption is not existing.
*
* @param	PartitionParams is a pointer to XFsblPs_PlPartition
* @param	Address start address of the authentication block.
* @param	BlockLen size of the authentication block.
* @param	NoOfChunks holds the no of chunks for the provided block
*
* @return
* 		Error code on failure
* 		XFSBL_SUCESS on success
*
* @note		None.
*
******************************************************************************/
static u32 XFsbl_ReAuthenticationBlock(XFsblPs_PlPartition *PartitionParams,
				UINTPTR Address, u32 BlockLen, u32 NoOfChunks)
{
	u32 Status;
	u32 Index;
	u32 Len = PartitionParams->ChunkSize;;
	UINTPTR Offset;
	u8 ChunksHash[48];
	XSecure_Sha3 SecureSha3;
	u32 HashDataLen = BlockLen;
	u8 *HashStored = PartitionParams->PlAuth.HashsOfChunks;
	(void)memset(ChunksHash,0U,sizeof(ChunksHash));

	Status = XSecure_Sha3Initialize(&SecureSha3,
			PartitionParams->CsuDmaPtr);
	if (Status != XFSBL_SUCCESS) {
		return Status;
	}
	XSecure_Sha3Start(&SecureSha3);

	/* calculating hashs for all chunks copies to AES/PCAP */
	for (Index = 0; Index < NoOfChunks; Index++) {
			/* Last chunk */
			if (Index == NoOfChunks -1) {
				Len = HashDataLen;
			}
			Offset = (UINTPTR)Address +
				(u64)(PartitionParams->ChunkSize * Index);

			/* Copy from DDR or flash to Buffer */
			Status = XFsbl_CopyData(PartitionParams,
						PartitionParams->ChunkBuffer,
							(u8 *)Offset, Len);
			if (Status != XFSBL_SUCCESS) {
				return Status;
			}
			/* Calculating hash for each chunk */
			XSecure_Sha3Update(&SecureSha3,
				PartitionParams->ChunkBuffer, Len);
			XSecure_Sha3_ReadHash(&SecureSha3, (u8 *)ChunksHash);

			/* Comparing with stored Hashs */
			Status = XFsbl_CompareHashs(HashStored, ChunksHash,
					PartitionParams->PlAuth.AuthType);
			if (Status != XFSBL_SUCCESS) {
				XFsbl_Printf(DEBUG_GENERAL,
					"XFsbl_PlReAuth:"
				" XFSBL_ERROR_CHUNK_HASH_COMPARISON\r\n");
				XFsbl_PrintArray(DEBUG_INFO, HashStored,
					PartitionParams->PlAuth.AuthType,
					"Stored Chunk Hash");
				XFsbl_PrintArray(DEBUG_INFO, ChunksHash,
					PartitionParams->PlAuth.AuthType,
					"Calculated chunk Hash");
				Status = XFSBL_ERROR_CHUNK_HASH_COMPARISON;
				goto END;
			}
			/* Remaining block size will be in HashDataLen */
			HashDataLen = HashDataLen - PartitionParams->ChunkSize;
			if (Index+1 <= NoOfChunks - 1) {
				HashStored = HashStored +
					PartitionParams->PlAuth.AuthType;
			}

			/* If image is not encrypted */
			if (PartitionParams->IsEncrypted == FALSE) {
				/* Configure Secure stream swith to PCAP */
				XFsbl_Out32(CSU_CSU_SSS_CFG,
					XFSBL_CSU_SSS_SRC_SRC_DMA <<
					CSU_CSU_SSS_CFG_PCAP_SSS_SHIFT);

				/* Copy bitstream to PCAP */
				XFsbl_DmaPlCopy(PartitionParams->CsuDmaPtr,
					(UINTPTR)PartitionParams->ChunkBuffer,
						Len/4, 0);

				Status = XFsbl_PcapWaitForDone();
				if (Status != XFSBL_SUCCESS) {
					goto END;
				}
			}
			/* If image is encrypted */
			else {
				Status = XFsbl_DecrptPlChunks(PartitionParams,
					(UINTPTR)PartitionParams->ChunkBuffer, Len);
				if (Status != XFSBL_SUCCESS) {
					goto END;
				}
			}
		}

END:
	return Status;

}