/**
 * This function checks if PMU FW is loaded and gives handoff to PMU Microblaze
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number of the image
 *
 * @return	None
 *
 *****************************************************************************/
static void XFsbl_CheckPmuFw(XFsblPs * FsblInstancePtr, u32 PartitionNum)
{

	u32 DestinationDev;
	u32 DestinationDevNxt = 0;
	u32 PmuFwLoadDone = FALSE;

	DestinationDev = XFsbl_GetDestinationDevice(
			&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum]);

	if (DestinationDev == XIH_PH_ATTRB_DEST_DEVICE_PMU) {
		if ((PartitionNum + 1) <
				(FsblInstancePtr->
						ImageHeader.ImageHeaderTable.NoOfPartitions-1U)) {
			DestinationDevNxt = XFsbl_GetDestinationDevice(
					&FsblInstancePtr->
					ImageHeader.PartitionHeader[PartitionNum + 1]);
			if (DestinationDevNxt != XIH_PH_ATTRB_DEST_DEVICE_PMU) {
				/* there is a partition after this but that is not PMU FW */
				PmuFwLoadDone = TRUE;
			}
		}
		else
		{
			/* the current partition is last PMU FW partition */
			PmuFwLoadDone = TRUE;
		}
	}

	/* If all partitions of PMU FW loaded, handoff it to PMU MicroBlaze */
	if (TRUE == PmuFwLoadDone)
	{
		/* Wakeup the processor */
		XFsbl_Out32(PMU_GLOBAL_GLOBAL_CNTRL,
				XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) | 0x1);

		/* wait until done waking up */
		while((XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) &
				PMU_GLOBAL_GLOBAL_CNTRL_FW_IS_PRESENT_MASK) !=
						PMU_GLOBAL_GLOBAL_CNTRL_FW_IS_PRESENT_MASK ) {;}

	}

}
/**
 * This function validates the partition
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number in the image to be loaded
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *
 *****************************************************************************/
static u32 XFsbl_PartitionValidation(XFsblPs * FsblInstancePtr,
						u32 PartitionNum)
{
	u32 Status=XFSBL_SUCCESS;
	u32 ChecksumType=0U;
	s32 IsEncryptionEnabled=FALSE;
	s32 IsAuthenticationEnabled=FALSE;
	u32 DestinationDevice=0U;
	u32 DestinationCpu=0U;
	u32 ExecState=0U;
	u32 CpuNo=0U;
	XFsblPs_PartitionHeader * PartitionHeader;
#if defined(XFSBL_RSA)
	u32 HashLen=0U;
#endif
#if defined(XFSBL_AES)
	u32 ImageOffset = 0U;
	u32 FsblIv[XIH_BH_IV_LENGTH / 4U];
	u32 UnencryptedLength = 0;
	u32 IvLocation;
#endif
#if defined(XFSBL_RSA) || defined(XFSBL_AES)
	u32 Length=0U;
#endif
#if defined(XFSBL_RSA) || defined(XFSBL_AES) || defined(XFSBL_BS)
	PTRSIZE LoadAddress=0U;
#endif
#if defined(XFSBL_BS)
	u32 BitstreamWordSize = 0;
#endif

	/**
	 * Update the variables
	 */
	PartitionHeader =
	    &FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];
	ChecksumType = XFsbl_GetChecksumType(PartitionHeader);

	/**
	 * Check the encryption status
	 */
	if (XFsbl_IsEncrypted(PartitionHeader) ==
			XIH_PH_ATTRB_ENCRYPTION )
	{
		IsEncryptionEnabled = TRUE;

#ifdef XFSBL_AES
		/* Copy the Iv from Flash into local memory */
		IvLocation = ImageOffset + XIH_BH_IV_OFFSET;

		Status = FsblInstancePtr->DeviceOps.DeviceCopy(IvLocation,
				(PTRSIZE) FsblIv, XIH_BH_IV_LENGTH);

		if (Status != XFSBL_SUCCESS) {
			XFsbl_Printf(DEBUG_GENERAL,
					"XFSBL_ERROR_DECRYPTION_IV_COPY_FAIL \r\n");
			Status = XFSBL_ERROR_DECRYPTION_IV_COPY_FAIL;
			goto END;
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_AES_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_AES_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * check the authentication status
	 */
	if (XFsbl_IsRsaSignaturePresent(PartitionHeader) ==
			XIH_PH_ATTRB_RSA_SIGNATURE )
	{
		IsAuthenticationEnabled = TRUE;
	}
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);
	DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader);


	/**
         * Get the execution state
         */
        ExecState = XFsbl_GetA53ExecState(PartitionHeader);

	/**
	 * if destination cpu is not present, it means it is for same cpu
	 */
	if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE)
	{
		DestinationCpu = FsblInstancePtr->ProcessorID;
	}


	/**
	 * Checksum Validation
	 */
	if (ChecksumType == XIH_PH_ATTRB_CHECKSUM_MD5)
	{
		/**
		 * Do the checksum validation
		 */
	}

#if defined(XFSBL_RSA) || defined(XFSBL_AES)
	if ((IsAuthenticationEnabled == TRUE) || (IsEncryptionEnabled == TRUE))
	{
		LoadAddress = PartitionHeader->DestinationLoadAddress;
		Length = PartitionHeader->TotalDataWordLength * 4U;
		Status = XFsbl_GetLoadAddress(DestinationCpu,
				&LoadAddress, Length);
		if (XFSBL_SUCCESS != Status)
		{
			goto END;
		}
	}
#endif

#ifdef XFSBL_BS
	if ((DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL) &&
			(LoadAddress == 0U))
	{
		LoadAddress = XFSBL_DDR_TEMP_ADDRESS;
	}
#endif

	/**
	 * Authentication Check
	 */
	if (IsAuthenticationEnabled == TRUE)
	{
		XFsbl_Printf(DEBUG_INFO,"Authentication Enabled\r\n");
#ifdef XFSBL_RSA
		/**
		 * Get the Sha type to be used from
		 * boot header attributes
		 */
		if ((FsblInstancePtr->BootHdrAttributes &
			XIH_BH_IMAGE_ATTRB_SHA2_MASK) ==
			XIH_BH_IMAGE_ATTRB_SHA2_MASK)
		{
			HashLen = XFSBL_HASH_TYPE_SHA2;
		} else {
			HashLen = XFSBL_HASH_TYPE_SHA3;
		}

		/**
		 * cache disbale can be removed
		 */
		Xil_DCacheDisable();

		/**
		 * Do the authentication validation
		 */
		Status = XFsbl_Authentication(FsblInstancePtr, LoadAddress, Length,
			(LoadAddress + Length) - XFSBL_AUTH_CERT_MIN_SIZE,
			HashLen);

		if (Status != XFSBL_SUCCESS)
                {
                        goto END;
                }
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_RSA_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_RSA_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * Decrypt image through CSU DMA
	 */
	if (IsEncryptionEnabled == TRUE) {
		XFsbl_Printf(DEBUG_INFO, "Decryption Enabled\r\n");
#ifdef XFSBL_AES

		/* AES expects IV in big endian form */
		FsblIv[0] = Xil_Htonl(FsblIv[0]);
		FsblIv[1] = Xil_Htonl(FsblIv[1]);
		FsblIv[2] = Xil_Htonl(FsblIv[2]);

		/* Initialize the Aes Instance so that it's ready to use */
		XSecure_AesInitialize(&SecureAes, &CsuDma,
		 XSECURE_CSU_AES_KEY_SRC_DEV, FsblIv, NULL);

		XFsbl_Printf(DEBUG_INFO, " Aes initialized \r\n");

		UnencryptedLength = PartitionHeader->UnEncryptedDataWordLength * 4U;


		if (DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PL) {
			Status = XSecure_AesDecrypt(&SecureAes, (u8 *) LoadAddress,
					(u8 *) LoadAddress, UnencryptedLength);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_DECRYPTION_FAIL;
				XFsbl_Printf(DEBUG_GENERAL, "XFSBL_ERROR_DECRYPTION_FAIL\r\n");
				goto END;
			} else {
				XFsbl_Printf(DEBUG_GENERAL, "Decryption Successful\r\n");
			}
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_AES_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_AES_NOT_ENABLED;
		goto END;
#endif
	}

#ifdef XFSBL_BS
	/**
	 * for PL image use CSU DMA to route to PL
	 */
	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
		/**
		 * Fsbl hook before bit stream download
		 */
		Status = XFsbl_HookBeforeBSDownload();
		if (Status != XFSBL_SUCCESS)
		{
			Status = XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD;
			XFsbl_Printf(DEBUG_GENERAL,
			 "XFSBL_ERROR_HOOK_BEFORE_BITSTREAM_DOWNLOAD\r\n");
			goto END;
		}

		XFsbl_Printf(DEBUG_GENERAL, "Bitstream download to start now\r\n");

		Status = XFsbl_PcapInit();
		if (Status != XFSBL_SUCCESS) {
			goto END;
		}

		if (IsEncryptionEnabled == TRUE) {
#ifdef XFSBL_AES
			/*
			 * The secure bitstream would be sent through CSU DMA to AES
			 * and the decrypted bitstream is sent directly to PCAP
			 * by configuring SSS appropriately
			 */
			Status = XSecure_AesDecrypt(&SecureAes,
					(u8 *) XFSBL_DESTINATION_PCAP_ADDR,
					(u8 *) LoadAddress, UnencryptedLength);

			if (Status != XFSBL_SUCCESS) {
				Status = XFSBL_ERROR_BITSTREAM_DECRYPTION_FAIL;
				XFsbl_Printf(DEBUG_GENERAL,
						"XFSBL_ERROR_BITSTREAM_DECRYPTION_FAIL\r\n");
				/* Reset PL */
				XFsbl_Out32(CSU_PCAP_PROG, 0x0);
				goto END;
			} else {
				XFsbl_Printf(DEBUG_GENERAL,
						"Bitstream decryption Successful\r\n");
			}
#endif
		}
		else {

			/* Use CSU DMA to load Bit stream to PL */
			BitstreamWordSize = PartitionHeader->UnEncryptedDataWordLength;

			Status = XFsbl_WriteToPcap(BitstreamWordSize, (u8 *) LoadAddress);
			if (Status != XFSBL_SUCCESS) {
				goto END;
			}
		}

		Status = XFsbl_PLWaitForDone();
		if (Status != XFSBL_SUCCESS) {
			goto END;
		}

		/**
		 * Fsbl hook after bit stream download
		 */
		Status = XFsbl_HookAfterBSDownload();
		if (Status != XFSBL_SUCCESS)
		{
			Status = XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD;
			XFsbl_Printf(DEBUG_GENERAL,
			 "XFSBL_ERROR_HOOK_AFTER_BITSTREAM_DOWNLOAD\r\n");
			goto END;
		}
	}
#endif

	/**
	 * Update the handoff details
	 */
	if ((DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PL) &&
			(DestinationDevice != XIH_PH_ATTRB_DEST_DEVICE_PMU))
	{
		CpuNo = FsblInstancePtr->HandoffCpuNo;
		if (XFsbl_CheckHandoffCpu(FsblInstancePtr,
				DestinationCpu) == XFSBL_SUCCESS)
		{
			FsblInstancePtr->HandoffValues[CpuNo].CpuSettings =
					DestinationCpu | ExecState;
			FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress =
					PartitionHeader->DestinationExecutionAddress;
			FsblInstancePtr->HandoffCpuNo += 1U;
		}
	}

END:
	return Status;
}
/**
 * This function copies the partition to specified destination
 *
 * @param	FsblInstancePtr is pointer to the XFsbl Instance
 *
 * @param	PartitionNum is the partition number in the image to be loaded
 *
 * @return	returns the error codes described in xfsbl_error.h on any error
 * 			returns XFSBL_SUCCESS on success
 *****************************************************************************/
static u32 XFsbl_PartitionCopy(XFsblPs * FsblInstancePtr, u32 PartitionNum)
{
	u32 Status=XFSBL_SUCCESS;
	u32 DestinationCpu=0U;
	u32 CpuNo=0U;
	u32 DestinationDevice=0U;
	u32 ExecState=0U;
	XFsblPs_PartitionHeader * PartitionHeader;
	u32 SrcAddress=0U;
	PTRSIZE LoadAddress=0U;
	u32 Length=0U;
	u32 RunningCpu=0U;

	/**
	 * Assign the partition header to local variable
	 */
	PartitionHeader =
		&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];

	RunningCpu = FsblInstancePtr->ProcessorID;

	/**
	 * Check for XIP image
	 * No need to copy for XIP image
	 */
	DestinationCpu = XFsbl_GetDestinationCpu(PartitionHeader);

	/**
	 * Get the execution state
	 */
	ExecState = XFsbl_GetA53ExecState(PartitionHeader);

	/**
	 * if destination cpu is not present, it means it is for same cpu
	 */
	if (DestinationCpu == XIH_PH_ATTRB_DEST_CPU_NONE)
	{
		DestinationCpu = FsblInstancePtr->ProcessorID;
	}

	if (PartitionHeader->UnEncryptedDataWordLength == 0U)
	{
		/**
		 * Update the Handoff address only for the first application
		 * of that cpu
		 * This is for XIP image. For other partitions it handoff
		 * address is updated after partition validation
		 */
		CpuNo = FsblInstancePtr->HandoffCpuNo;
		if (XFsbl_CheckHandoffCpu(FsblInstancePtr,
				DestinationCpu) == XFSBL_SUCCESS)
		{
			FsblInstancePtr->HandoffValues[CpuNo].CpuSettings =
			        DestinationCpu | ExecState;
			FsblInstancePtr->HandoffValues[CpuNo].HandoffAddress =
				PartitionHeader->DestinationExecutionAddress;
			FsblInstancePtr->HandoffCpuNo += 1U;
		} else {
			/**
			 *
			 * if two partitions has same destination cpu, error can
			 * be triggered here
			 */
		}
		Status = XFSBL_SUCCESS;
		goto END;
	}

	/**
	 * Copy the PL to temporary DDR Address
	 * Copy the PS to Load Address
	 * Copy the PMU firmware to PMU RAM
	 */
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);
	LoadAddress = PartitionHeader->DestinationLoadAddress;

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
#ifdef XFSBL_BS

		if (LoadAddress == XFSBL_DUMMY_PL_ADDR)
		{
			LoadAddress = XFSBL_DDR_TEMP_ADDRESS;
		}
#else
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_PL_NOT_ENABLED \r\n");
		Status = XFSBL_ERROR_PL_NOT_ENABLED;
		goto END;
#endif
	}

	/**
	 * Get the source(flash offset) address where it needs to copy
	 */
	SrcAddress = FsblInstancePtr->ImageOffsetAddress +
				((PartitionHeader->DataWordOffset) *
					XIH_PARTITION_WORD_LENGTH);

	/**
	 * Length of the partition to be copied
	 */
	Length  = (PartitionHeader->TotalDataWordLength) *
					XIH_PARTITION_WORD_LENGTH;


	/**
	 * When destination device is R5-0/R5-1/R5-L and load address is in TCM
	 * copy to high address of TCM address map
	 * Update the LoadAddress
	 */
	Status = XFsbl_GetLoadAddress(DestinationCpu, &LoadAddress, Length);
	if (XFSBL_SUCCESS != Status)
	{
		goto END;
	}

	/**
	 * Configure the memory
	 */
	XFsbl_ConfigureMemory(RunningCpu, DestinationCpu,
						LoadAddress, Length);

	/**
	 *
	 * Do not copy the IVT if FSBL is running in R5-0/R5-L at 0x0 TCM
	 * Update the SrcAddress, LoadAddress and Len based on the
	 * above condition
	 */
#if 1
	if (((FsblInstancePtr->ProcessorID ==
			XIH_PH_ATTRB_DEST_CPU_R5_0) ||
		(FsblInstancePtr->ProcessorID ==
				XIH_PH_ATTRB_DEST_CPU_R5_L)) &&
		((LoadAddress > XFSBL_R50_HIGH_TCM_START_ADDRESS) &&
		(LoadAddress <
			XFSBL_R50_HIGH_TCM_START_ADDRESS + XFSBL_IVT_LENGTH)))
	{

		/**
		 * Get the length of the IVT area to be
		 * skipped from Load Address
		 */
		TcmSkipAddress = LoadAddress/XFSBL_IVT_LENGTH;
		TcmSkipLength = XFSBL_IVT_LENGTH - TcmSkipAddress;

		/**
		 * Check if Length is less than SkipLength
		 */
		if (TcmSkipLength > Length)
		{
			TcmSkipLength = Length;
		}

		/**
		 * Copy the Skip length to a local array
		 */
		Status = FsblInstancePtr->DeviceOps.DeviceCopy(SrcAddress,
				(PTRSIZE )TcmVectorArray, TcmSkipLength);
		if (XFSBL_SUCCESS != Status)
		{
			goto END;
		}

		SrcAddress += TcmSkipLength;
		LoadAddress +=  TcmSkipLength;
		Length -= TcmSkipLength;
	}
#endif

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PMU)
	{
		/* Enable PMU_0 IPI */
		XFsbl_Out32(IPI_PMU_0_IER, IPI_PMU_0_IER_PMU_0_MASK);

		/* Trigger PMU0 IPI in PMU IPI TRIG Reg */
		XFsbl_Out32(IPI_PMU_0_TRIG, IPI_PMU_0_TRIG_PMU_0_MASK);

		/**
		 * Wait until PMU Microblaze goes to sleep state,
		 * before starting firmware download to PMU RAM
		 */
		while((XFsbl_In32(PMU_GLOBAL_GLOBAL_CNTRL) &
				PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK) !=
						PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK ) {;}
	}

	/**
	 * Copy the partition to PS_DDR/PL_DDR/TCM
	 */
	Status = FsblInstancePtr->DeviceOps.DeviceCopy(SrcAddress,
					LoadAddress, Length);
	if (XFSBL_SUCCESS != Status)
	{
		goto END;
	}

END:
	return Status;
}
예제 #4
0
/**
 * Configure the RSA and SHA for the SPK
 * Signature verification.
 * If SPK Signature verification fails
 * then return unique error code saying
 * XFSBL_STAGE3_SPK_SIGN_VERIF_ERROR.
 *
 * @param
 *
 * @return
 *
 ******************************************************************************/
u32 XFsbl_SpkVer(XFsblPs *FsblInstancePtr , u64 AcOffset, u32 HashLen,
			u32 PartitionNum)
{
	u8 SpkHash[XFSBL_HASH_TYPE_SHA3] __attribute__ ((aligned (4)));
	u8 * PpkModular = (u8 *)NULL;
	u8 * PpkModularEx = (u8 *)NULL;
	u32 PpkExp = 0;
	u8 * AcPtr = (u8*) (PTRSIZE) AcOffset;
	u32 Status = XFSBL_SUCCESS;
	void * ShaCtx = (void * )NULL;
	u8 XFsbl_RsaSha3Array[512];

#ifdef XFSBL_SHA2
	sha2_context ShaCtxObj;
	ShaCtx = &ShaCtxObj;
#endif

#ifndef XFSBL_PS_DDR
	XFsblPs_PartitionHeader * PartitionHeader;
	u32 DestinationDevice = 0U;
	PartitionHeader =
		&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
		/*
		 * If it is DDR less system, bitstream chunk containing
		 * Authentication Certificate has to be read from boot device
		 */
		if(XFSBL_SUCCESS != FsblInstancePtr->DeviceOps.DeviceCopy(
					(INTPTR)AcPtr, (PTRSIZE)ReadBuffer,
					XFSBL_AUTH_CERT_MIN_SIZE)) {
			XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_SpkVer: Device to OCM copy of certificate failed \r\n");
			Status = XFSBL_ERROR_SPK_RSA_DECRYPT;
			goto END;
		}

		/* Repoint Auth. cert. pointer to OCM buffer beginning*/
		AcPtr = ReadBuffer;
	}
#endif

	/* Re-initialize CSU DMA. This is a workaround and need to be removed */
	Status = XFsbl_CsuDmaInit();
	if (XST_SUCCESS != Status) {
		goto END;
	}

	(void)XFsbl_ShaStart(ShaCtx, HashLen);

	/* Hash the PPK + SPK choice */
	XFsbl_ShaUpdate(ShaCtx, AcPtr, 8, HashLen);

	/* Set PPK pointer */
	AcPtr += XFSBL_RSA_AC_ALIGN;
	PpkModular = (u8 *)AcPtr;
	AcPtr += XFSBL_PPK_MOD_SIZE;
	PpkModularEx = (u8 *)AcPtr;
	AcPtr += XFSBL_PPK_MOD_EXT_SIZE;
	PpkExp = *((u32 *)AcPtr);
	AcPtr += XFSBL_RSA_AC_ALIGN;

	XFsbl_Printf(DEBUG_DETAILED,
		"XFsbl_SpkVer: Ppk Mod %0x, Ppk Mod Ex %0x, Ppk Exp %0x\r\n",
		PpkModular, PpkModularEx, PpkExp);

	/* Calculate SPK + Auth header Hash */
	XFsbl_ShaUpdate(ShaCtx, (u8 *)AcPtr, XFSBL_SPK_SIZE, HashLen);

	XFsbl_ShaFinish(ShaCtx, (u8 *)SpkHash, HashLen);

	/* Set SPK Signature pointer */
	AcPtr += XFSBL_SPK_SIZE;

	XSecure_RsaInitialize(&SecureRsa, PpkModular,
				PpkModularEx, (u8 *)&PpkExp);

	/* Decrypt SPK Signature */
	if(XFSBL_SUCCESS !=
		XSecure_RsaDecrypt(&SecureRsa, AcPtr, XFsbl_RsaSha3Array))
	{
		XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_SpkVer: XFSBL_ERROR_SPK_RSA_DECRYPT\r\n");
		Status = XFSBL_ERROR_SPK_RSA_DECRYPT;
		goto END;
	}

	/* Authenticate SPK Signature */
	if(XFSBL_SUCCESS != XSecure_RsaSignVerification(XFsbl_RsaSha3Array,
							SpkHash, HashLen))
	{
		XFsbl_PrintArray(DEBUG_INFO, SpkHash,
				HashLen, "Calculated SPK Hash");
		XFsbl_PrintArray(DEBUG_INFO, XFsbl_RsaSha3Array,
				512, "RSA decrypted Hash");
		XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_SpkVer: XFSBL_ERROR_SPK_SIGNATURE\r\n");
		Status = XFSBL_ERROR_SPK_SIGNATURE;
	}

END:
	return Status;
}
예제 #5
0
/**
 * Configure the RSA and SHA for the
 * Boot Header Signature verification.
 * If Boot Header Signature verification
 * fails then return unique error code saying
 * XFSBL_STAGE3_BOOT_HDR_SIGN_VERIF_ERROR.
 *
 * @param
 *
 * @return
 *
 ******************************************************************************/
u32 XFsbl_PartitionSignVer(XFsblPs *FsblInstancePtr, u64 PartitionOffset,
				u32 PartitionLen, u64 AcOffset, u32 HashLen,
				u32 PartitionNum)
{

	u8 PartitionHash[XFSBL_HASH_TYPE_SHA3] __attribute__ ((aligned (4)));
	u8 * SpkModular = (u8 *)NULL;
	u8 * SpkModularEx = (u8 *)NULL;
	u32 SpkExp = 0;
	u8 * AcPtr = (u8*)(PTRSIZE) AcOffset;
	u32 Status = XFSBL_SUCCESS;
	u32 HashDataLen=0U;
#ifndef XFSBL_PS_DDR
	void * ShaCtx = (void * )NULL;
#endif
	u8 XFsbl_RsaSha3Array[512];

#ifdef XFSBL_SHA2
	sha2_context ShaCtxObj;
	ShaCtx = &ShaCtxObj;
#endif

	XFsbl_Printf(DEBUG_INFO, "Doing Partition Sign verification\r\n");

	/**
	 * hash to be calculated will be total length with AC minus
	 * signature size
	 */
	HashDataLen = PartitionLen - XFSBL_FSBL_SIG_SIZE;

	/* Calculate Partition Hash */
#ifndef XFSBL_PS_DDR
	XFsblPs_PartitionHeader * PartitionHeader;
	u32 DestinationDevice = 0U;
	PartitionHeader =
		&FsblInstancePtr->ImageHeader.PartitionHeader[PartitionNum];
	DestinationDevice = XFsbl_GetDestinationDevice(PartitionHeader);

	if (DestinationDevice == XIH_PH_ATTRB_DEST_DEVICE_PL)
	{
		/**
		 * bitstream partion in DDR less system, Chunk by chunk copy
		 * into OCM and update SHA module
		 */
		u32 NumChunks = 0U;
		u32 RemainingBytes = 0U;
		u32 Index = 0U;
		u32 StartAddrByte = PartitionOffset;

		NumChunks = HashDataLen / READ_BUFFER_SIZE;
		RemainingBytes = (HashDataLen % READ_BUFFER_SIZE);

		/* Start the SHA engine */
		(void)XFsbl_ShaStart(ShaCtx, HashLen);

		XFsbl_Printf(DEBUG_INFO,
			"XFsbl_PartitionVer: NumChunks :%0d, RemainingBytes : %0d \r\n",
			NumChunks, RemainingBytes);

		for(Index = 0; Index < NumChunks; Index++)
		{
			if(XFSBL_SUCCESS !=FsblInstancePtr->DeviceOps.DeviceCopy(
					StartAddrByte, (PTRSIZE)ReadBuffer,
					READ_BUFFER_SIZE))
			{
				XFsbl_Printf(DEBUG_GENERAL,
					"XFsblPartitionVer: Device "
					"to OCM copy of partition failed \r\n");
				XFsbl_Printf(DEBUG_GENERAL,
				"XFsbl_PartitionVer: XFSBL_ERROR_PART_RSA_DECRYPT\r\n");
				Status = XFSBL_ERROR_PART_RSA_DECRYPT;
				goto END;
			}

			XFsbl_ShaUpdate(ShaCtx, (u8 *)ReadBuffer,
						READ_BUFFER_SIZE, HashLen);

			StartAddrByte += READ_BUFFER_SIZE;
		}

		/* Send the residual bytes if Size is not buffer size multiple */
		if(RemainingBytes != 0)
		{
			if(XFSBL_SUCCESS!=FsblInstancePtr->DeviceOps.DeviceCopy(
						StartAddrByte, (PTRSIZE)ReadBuffer,
						RemainingBytes))
			{
				XFsbl_Printf(DEBUG_GENERAL,
				"XFsbl_PartitionVer: XFSBL_ERROR_PART_RSA_DECRYPT\r\n");

				Status = XFSBL_ERROR_PART_RSA_DECRYPT;
				goto END;
			}

			XFsbl_ShaUpdate(ShaCtx, (u8 *)ReadBuffer,
						RemainingBytes, HashLen);
		}

		XFsbl_ShaFinish(ShaCtx, PartitionHash, HashLen);

		/**
		 * Copy Auth. Certificate to OCM buffer location
		 * Assign AcPtr to OCM buffer location
		 */
		if(XFSBL_SUCCESS != FsblInstancePtr->DeviceOps.DeviceCopy(
					(u32)(INTPTR)AcPtr, (PTRSIZE)ReadBuffer,
					XFSBL_AUTH_CERT_MIN_SIZE)) {
			XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_PartitionVer: Flash to OCM copy failed \r\n");
			Status = XFSBL_ERROR_SPK_RSA_DECRYPT;
			goto END;
		}

		/* Repoint Auth. Certificate pointer to start of OCM buffer */
		AcPtr = ReadBuffer;
	}
	else
	{
		XFsbl_Printf(DEBUG_INFO, "partver: sha calc. "
					"for non bs DDR less part \r\n");
		/* SHA calculation for non-bitstream, DDR less partitions */
		XFsbl_ShaDigest((const u8 *)(PTRSIZE)PartitionOffset,
					HashDataLen, PartitionHash, HashLen);
	}
#else
	/* SHA calculation in DDRful systems */
	XFsbl_ShaDigest((const u8 *)(PTRSIZE)PartitionOffset,
			HashDataLen, PartitionHash, HashLen);
#endif

	/* Set SPK pointer */
	AcPtr += (XFSBL_RSA_AC_ALIGN + XFSBL_PPK_SIZE);
	SpkModular = (u8 *)AcPtr;
	AcPtr += XFSBL_SPK_MOD_SIZE;
	SpkModularEx = (u8 *)AcPtr;
	AcPtr += XFSBL_SPK_MOD_EXT_SIZE;
	SpkExp = *((u32 *)AcPtr);
	AcPtr += XFSBL_RSA_AC_ALIGN;

	/* Increment by  SPK Signature pointer */
	AcPtr += XFSBL_SPK_SIG_SIZE;
	/* Increment by  BHDR Signature pointer */
	AcPtr += XFSBL_BHDR_SIG_SIZE;

	XFsbl_Printf(DEBUG_DETAILED,
		"XFsbl_PartVer: Spk Mod %0x, Spk Mod Ex %0x, Spk Exp %0x\r\n",
		SpkModular, SpkModularEx, SpkExp);

	XFsbl_Printf(DEBUG_INFO,
			"Partition Verification done \r\n");

	XSecure_RsaInitialize(&SecureRsa, SpkModular,
				SpkModularEx, (u8 *)&SpkExp);
	/* Decrypt Partition Signature. */
	if(XFSBL_SUCCESS !=
		XSecure_RsaDecrypt(&SecureRsa, AcPtr, XFsbl_RsaSha3Array))
	{
		XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_SpkVer: XFSBL_ERROR_PART_RSA_DECRYPT\r\n");
		Status = XFSBL_ERROR_PART_RSA_DECRYPT;
		goto END;
	}

	/* Authenticate Partition Signature */
	if(XFSBL_SUCCESS != XSecure_RsaSignVerification(XFsbl_RsaSha3Array,
				PartitionHash, HashLen))
	{
		XFsbl_PrintArray(DEBUG_INFO, PartitionHash,
				HashLen, "Calculated Partition Hash");
		XFsbl_PrintArray(DEBUG_INFO, XFsbl_RsaSha3Array,
				512, "RSA decrypted Hash");
		XFsbl_Printf(DEBUG_GENERAL,
			"XFsbl_PartVer: XFSBL_ERROR_PART_SIGNATURE\r\n");
		Status = XFSBL_ERROR_PART_SIGNATURE;
		goto END;
	}

END:
	return Status;
}