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