/******************************************************************************
*
* 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;

}
예제 #2
0
/**
 *
 * 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;

}