/** * * Calculate SHA-3 Digest on the given input data * * @param InstancePtr is a pointer to the XSecure_Sha3 instance. * @param In is the pointer to the input data for hashing * @param Size of the input data * @param Out is the pointer to location where resulting hash will be * written. * * @return None * * @note None * ******************************************************************************/ void XSecure_Sha3Digest(XSecure_Sha3 *InstancePtr, const u8 *In, const u32 Size, u8 *Out) { /* Asserts validate the input arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Size != (u32)0x00U); Xil_AssertVoid(Out != NULL); XSecure_Sha3Start(InstancePtr); XSecure_Sha3Update(InstancePtr, In, Size); XSecure_Sha3Finish(InstancePtr, Out); }
/****************************************************************************** * * This function performs authentication and RSA signature verification for * each block. * * @param PartitionParams is a pointer to XFsblPs_PlPartition * @param BlockAdrs is the block start address * @param BlockSize is the block size * @param AcOffset holds authentication certificate's address * @param NoOfChunks for the provided block * * @return * Error code on failure * XFSBL_SUCESS on success * * @note None * ******************************************************************************/ static u32 XFsbl_PlSignVer(XFsblPs_PlPartition *PartitionParams, UINTPTR BlockAdrs, u32 BlockSize, u8 *AcOffset, u32 NoOfChunks) { u8 PartitionHash[XFSBL_HASH_TYPE_SHA3]={0U}; u8 * SpkModular; u8* SpkModularEx; u32 SpkExp; u8 * AcPtr = (u8*)AcOffset; u32 Status; u32 HashDataLen = BlockSize; u8 XFsbl_RsaSha3Array[512] = {0U}; s32 SStatus; u8 *ChunksHash = PartitionParams->PlAuth.HashsOfChunks; XSecure_Sha3 SecureSha3={0U}; XSecure_Rsa SecureRsa={0U}; u32 Index; u32 Len = PartitionParams->ChunkSize; u64 Offset; /* Start the SHA engine */ if (XSECURE_HASH_TYPE_SHA3 == PartitionParams->PlAuth.AuthType) { XCsuDma_Configure ConfigurValues = {0}; /* this needs to be modified at encryption */ XCsuDma_GetConfig(PartitionParams->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); ConfigurValues.EndianType = 0U; XCsuDma_SetConfig(PartitionParams->CsuDmaPtr, XCSUDMA_SRC_CHANNEL, &ConfigurValues); (void)XSecure_Sha3Initialize(&SecureSha3, PartitionParams->CsuDmaPtr); XSecure_Sha3Start(&SecureSha3); } /* SHA calculation */ for (Index = 0; Index < NoOfChunks; Index++) { /* * If the block is the last it may not be complete block size * mentioned so will break if it is less than chunk size */ if ((Index == NoOfChunks-1) || (HashDataLen < PartitionParams->ChunkSize)) { Len = HashDataLen; } Offset = (u64)BlockAdrs + (u64)(PartitionParams->ChunkSize * Index); Status = XFsbl_CopyData(PartitionParams, PartitionParams->ChunkBuffer, (u8 *)(UINTPTR)Offset, Len); if (Status != XFSBL_SUCCESS) { return Status; } XSecure_Sha3Update(&SecureSha3, PartitionParams->ChunkBuffer, Len); XSecure_Sha3_ReadHash(&SecureSha3, (u8 *)ChunksHash); if (Index+1 < NoOfChunks) { HashDataLen = HashDataLen - PartitionParams->ChunkSize; ChunksHash = ChunksHash + PartitionParams->PlAuth.AuthType; } } /* Calculate hash for (AC - signature size) */ XSecure_Sha3Update(&SecureSha3, (u8 *)AcOffset, (XFSBL_AUTH_CERT_MIN_SIZE - XFSBL_FSBL_SIG_SIZE)); XSecure_Sha3Finish(&SecureSha3, (u8 *)PartitionHash); /* Set SPK pointer */ AcPtr += (XFSBL_RSA_AC_ALIGN + XFSBL_PPK_SIZE); SpkModular = AcPtr; AcPtr += XFSBL_SPK_MOD_SIZE; SpkModularEx = 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; if((SpkModular != NULL) && (SpkModularEx != NULL)) { XFsbl_Printf(DEBUG_DETAILED, "XFsbl_PartVer: Spk Mod %0x, Spk Mod Ex %0x, Spk Exp %0x\r\n", SpkModular, SpkModularEx, SpkExp); } SStatus = XSecure_RsaInitialize(&SecureRsa, SpkModular, SpkModularEx, (u8 *)&SpkExp); if (SStatus != XFSBL_SUCCESS) { Status = XFSBL_ERROR_RSA_INITIALIZE; XFsbl_Printf(DEBUG_INFO, "XFSBL_ERROR_RSA_INITIALIZE at PL verification\r\n"); goto END; } /* Decrypt Partition Signature. */ if(XFSBL_SUCCESS != XSecure_RsaDecrypt(&SecureRsa, AcPtr, XFsbl_RsaSha3Array)) { XFsbl_Printf(DEBUG_INFO, "XFsbl_SpkVer: " "XFSBL_ERROR_PART_RSA_DECRYPT at PL verification\r\n"); Status = XFSBL_ERROR_PART_RSA_DECRYPT; goto END; } /* Authenticate Partition Signature */ if(XFSBL_SUCCESS != XSecure_RsaSignVerification(XFsbl_RsaSha3Array, PartitionHash, PartitionParams->PlAuth.AuthType)) { XFsbl_PrintArray(DEBUG_INFO, PartitionHash, PartitionParams->PlAuth.AuthType, "Calculated Partition Hash at PL verification"); XFsbl_PrintArray(DEBUG_INFO, XFsbl_RsaSha3Array, 512, "RSA decrypted Hash at PL verification"); Status = XFSBL_FAILURE; goto END; } Status = XFSBL_SUCCESS; END: 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; }