ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/obm/Common/SecureBoot/Security.c b/marvell/obm/Common/SecureBoot/Security.c
new file mode 100644
index 0000000..73b47b5
--- /dev/null
+++ b/marvell/obm/Common/SecureBoot/Security.c
@@ -0,0 +1,814 @@
+/****************************************************************************
+ *
+ * (C)Copyright 2005 - 2010 Marvell. All Rights Reserved.
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code. This Module contains Proprietary
+ * Information of Marvell and should be treated as Confidential. The
+ * information in this file is provided for the exclusive use of the
+ * licensees of Marvell. Such users have the right to use, modify, and
+ * incorporate this code into products for purposes authorized by the
+ * license agreement provided they include this notice and the associated
+ * copyright notice with any such product.
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ***************************************************************************/
+
+#include "Security.h"
+#include "tim.h"
+#include "misc.h"
+#include "PlatformConfig.h"
+
+#if USE_WTM3_TBR
+ #include "WTM3_TBR_Lib.h"
+ //#include "WTM3_TBR_Interrupts.h"
+ #include "self_test_vectors.h"
+#elif BL_USE_WTM_CRYPTO
+ #include "WTM3_MBOX_Interface.h"
+#elif ( USE_IPPCP_LIB || BL_USE_SECURITY_CALLBACK )
+ #include "crypt_lib.h"
+#endif
+
+#if ( USE_IPPCP_LIB || BL_USE_SECURITY_CALLBACK )
+#if (AARCH64)
+__align(8)
+#endif
+ // Passed in data buffer to replace the IPPCP Read/Write space in the library.
+#if ( ECDSA_SUPPORTED )
+ UINT8_T pECDSA_DataBuffer[10540]={0}; // For ECDSA - KeyBitLen=521
+#else
+ UINT8_T* pECDSA_DataBuffer = NULL;
+#endif
+#else
+ UINT8_T* pECDSA_DataBuffer = NULL; // Used mainly for building non-IPPCP platforms.
+#endif
+
+
+// Generic pointers to security functions dynamically bound based on underlying security architecture.
+static SECURITY_FUNCTIONS SFs;
+
+pSECURITY_FUNCTIONS GetSecurityFunctionsPointer()
+{
+ return &SFs;
+}
+
+UINT8_T* GetECDSADataBufferPointer()
+{
+ return pECDSA_DataBuffer;
+}
+
+static UINT_T (*P_SHAMessageDigest) (const UINT8_T* pSrcMesgIn, UINT_T SrcMesgByteLen, \
+ UINT8_T* pMesgDigestOut, UINT_T DigestByteLen) = NULL;
+
+static UINT_T (*P_PKCS_DSA_Verify) (const UINT8_T* pSrcMesgIn, UINT_T SrcMesgByteLen, \
+ const pPLAT_DS pDSA, UINT8_T* DataBuffer) = NULL;
+
+static UINT_T SHAMessageDigest(const UINT8_T* pSrcMesgIn, UINT_T SrcMesgByteLen, \
+ UINT8_T* pMesgDigestOut, UINT_T DigestByteLen)
+{
+#if LAPW && !CP_BOOT
+ if(PlatformIsLapwB0() && HwHashIsUsed()) {
+ dcache_clean_range(pSrcMesgIn, SrcMesgByteLen);
+ dcache_clean_invalidate_range(pMesgDigestOut, DigestByteLen);
+ }
+#endif
+
+ if (!P_SHAMessageDigest)
+ return SecurityFunctionNotSupported;
+
+ return P_SHAMessageDigest(pSrcMesgIn, SrcMesgByteLen, pMesgDigestOut, DigestByteLen);
+}
+
+static UINT_T PKCS_DSA_Verify(const UINT8_T* pSrcMesgIn, UINT_T SrcMesgByteLen, \
+ const pPLAT_DS pDSA, UINT8_T* DataBuffer)
+{
+#if LAPW && !CP_BOOT
+ if(PlatformIsLapwB0() && HwHashIsUsed()) {
+ dcache_clean_range(pSrcMesgIn, SrcMesgByteLen);
+ dcache_clean_invalidate_range(DataBuffer, DATABUFFERSIZE);
+ }
+#endif
+
+ if (!P_PKCS_DSA_Verify)
+ return SecurityFunctionNotSupported;
+
+ return P_PKCS_DSA_Verify(pSrcMesgIn, SrcMesgByteLen, pDSA, DataBuffer);
+}
+
+/******************** SecurityInitialization ***************************************
+* This routine is in charge of doing any security Initialization needed
+********************************************************************************************/
+UINT_T SecurityInitialization(UINT_T ver_adv)
+{
+ UINT_T Retval = NoError;
+
+#if USE_WTM3_TBR
+ //WTM3_TBR_Enable_AES_Interrupts();
+ SFs.pInitializeSecurity = &WTM3_TBR_SecurityInitialization;
+ SFs.pSHAMessageDigest = &WTM3_TBR_SHAMessageDigest;
+ SFs.pPKCS_DSA_Verify = &WTM3_TBR_PKCS_DSA_Verify;
+ #if ECDSA_SUPPORTED
+ SFs.pECCP_DSA_Verify = &WTM3_TBR_ECCP_DSA_Verify;
+ #else
+ SFs.pECCP_DSA_Verify = NULL;
+ #endif
+ SFs.pGet_NonceBitLen = &WTM3_TBR_Get_NonceBitLen;
+ SFs.pGet_Nonce = &WTM3_TBR_Get_Nonce;
+ SFs.pAES_Decrypt = &WTM3_TBR_AES_DECRYPT;
+ SFs.pAES_Encrypt = &WTM3_TBR_AES_ENCRYPT;
+ SFs.pHMAC = NULL;
+#elif BL_USE_WTM_CRYPTO
+
+ SFs.pInitializeSecurity = &WTM3_MBOX_SecurityInitialization;
+ SFs.pSHAMessageDigest = &WTM3_MBOX_SHAMessageDigest;
+ SFs.pPKCS_DSA_Verify = &WTM3_MBOX_PKCS_DSA_Verify;
+#if ECDSA_SUPPORTED
+ SFs.pECCP_DSA_Verify = &WTM3_MBOX_ECCP_DSA_Verify;
+#else
+ SFs.pECCP_DSA_Verify = NULL;
+#endif
+ SFs.pGet_NonceBitLen = NULL; // This maybe implemented in future
+ SFs.pGet_Nonce = NULL; // This is supported by WTM Kernel (WTM_DRBG_GEN_RAN_BITS), maybe implemented in future
+ SFs.pAES_Decrypt = &WTM3_MBOX_AES_Decrypt;
+ SFs.pAES_Encrypt = &WTM3_MBOX_AES_Encrypt;
+ SFs.pHMAC = NULL;
+#elif USE_IPPCP_LIB
+ SFs.pInitializeSecurity = &IPPCP_SecurityInitialization;
+ SFs.pSHAMessageDigest = &IPPCP_SHAMessageDigest;
+ SFs.pPKCS_DSA_Verify = &IPPCP_PKCS_DSA_Verify;
+#if ECDSA_SUPPORTED
+#if ENABLE_NEON
+ SFs.pECCP_DSA_Verify = &IPPCP_ECCP_DSA_Verify;
+#else
+ SFs.pECCP_DSA_Verify = NULL;
+#endif
+#endif
+ SFs.pGet_NonceBitLen = IPPCP_Get_NonceBitLen;
+ SFs.pGet_Nonce = IPPCP_Get_Nonce;
+ SFs.pAES_Decrypt = NULL;
+ SFs.pAES_Encrypt = NULL;
+ SFs.pHMAC = NULL;
+#elif BL_USE_SECURITY_CALLBACK
+ SetSecurityCallBackFunctionPointers(); // Sets the SFs function pointers with supported call back functions
+ // This needs to be a platform specific call as different ROMs
+ // support different security functions.
+#endif
+
+ P_SHAMessageDigest = SFs.pSHAMessageDigest;
+ SFs.pSHAMessageDigest = &SHAMessageDigest;
+
+ P_PKCS_DSA_Verify = SFs.pPKCS_DSA_Verify;
+ SFs.pPKCS_DSA_Verify = &PKCS_DSA_Verify;
+
+ Retval = SFs.pInitializeSecurity(ver_adv);
+ return Retval;
+}
+
+/******************** SecurityShutdown*********************************************************
+* This routine should do Security Driver related cleanup and hardware shutdown
+************************************************************************************************/
+
+UINT_T SecurityShutdown()
+{
+ UINT_T Retval = NoError;
+#if BL_USE_WTM_CRYPTO
+ Retval = WTM3_MBOX_SecurityShutdown();
+#endif
+ return Retval;
+}
+
+/******************** ValidateTIMSignature ******************************************************
+* Validate the TIM structure
+* It is assumed that the TIM structure has already been loaded with a call to LoadTIM()
+* in flash.c
+*
+********************************************************************************************/
+UINT_T ValidateTIMSignature(pTIM pTIM_h)
+{
+ UINT_T Retval = NoError;
+ CHAR *Buffer = NULL, *AlignedBuffer;
+
+ switch (pTIM_h->pTBTIM_DS->DSAlgorithmID)
+ {
+ case PKCS1_v1_5_Ippcp:
+#if ECDSA_SUPPORTED
+ case ECDSA_256:
+ case ECDSA_521:
+#endif
+ case PKCS1_v2_2_Ippcp:
+ break;
+ default:
+ return InvalidSecureBootMethodError;
+ }
+
+ if ((pTIM_h->pTBTIM_DS->DSAlgorithmID == PKCS1_v1_5_Ippcp) || (pTIM_h->pTBTIM_DS->DSAlgorithmID == PKCS1_v2_2_Ippcp))
+ {
+ if (SFs.pPKCS_DSA_Verify != NULL) // Verify signature if this function is supported
+ {
+ if ( pTIM_h->pTBTIM_DS->HashAlgorithmID == SHA512) // SHA512 is not supported with PKCS
+ {
+ return SecurityFunctionNotSupported;
+ }
+ Buffer = malloc(ALIGN_UP(DATABUFFERSIZE, DCACHE_LINE_SIZE));
+ if (Buffer) {
+ AlignedBuffer = ALIGN_UP((UINT_T)Buffer, DCACHE_LINE_SIZE);
+ Retval = SFs.pPKCS_DSA_Verify( (UINT8_T*) pTIM_h->pConsTIM, pTIM_h->pImg[0].ImageSizeToHash, pTIM_h->pTBTIM_DS, AlignedBuffer);
+ free(Buffer);
+ } else{
+ return HeapExhaustedError;
+ }
+ }
+ else // Else, return not supported error
+ {
+ return SecurityFunctionNotSupported;
+ }
+ }
+#if ECDSA_SUPPORTED
+ else if ((pTIM_h->pTBTIM_DS->DSAlgorithmID == ECDSA_256) || (pTIM_h->pTBTIM_DS->DSAlgorithmID == ECDSA_521))
+ {
+ if (SFs.pECCP_DSA_Verify != NULL) // Verify signature if this function is supported
+ {
+ Retval = SFs.pECCP_DSA_Verify( (UINT8_T*) pTIM_h->pConsTIM, pTIM_h->pImg[0].ImageSizeToHash, pTIM_h->pTBTIM_DS, pECDSA_DataBuffer);
+ }
+ else // Else, return not supported error
+ {
+ return SecurityFunctionNotSupported;
+ }
+ }
+#endif
+ else {
+ return InvalidDSAError;
+ }
+
+ if (Retval != NoError)
+ return InvalidTIMImageError;
+
+ return NoError;
+}
+
+/******************** VerifySignature ******************************************************
+* Verify the DSA for any signature
+********************************************************************************************/
+UINT_T VerifySignature(const UINT8_T* pBufferToVerifyIn, UINT_T NumBytesToVerify, const UINT_T* pSignatureIn, const pKEY_MOD_3_4_0 pKeyIn, UINT_T ReverseSignatureBytes)
+{
+ UINT_T Retval = NoError;
+ //UINT_T KeyByteLen = (pKeyIn->KeySize +7)>>3;
+ UINT_T KeySizeInWords = (pKeyIn->KeySize==521) ? 17 : pKeyIn->KeySize/32;
+ PLAT_DS Signature;
+ CHAR *Buffer = NULL, *AlignedBuffer;
+ UINT_T i;
+ const pPLAT_DS pSignature = & Signature;
+
+ /* abandoned, ReverseSignatureBytes is always 0 in OBM
+ if(ReverseSignatureBytes) {
+ ReverseBytes((UINT8_T *)pSignatureIn, KeyByteLen); //reverse bytes for signature
+ }
+ */
+
+ Signature.DSAlgorithmID = pKeyIn->EncryptAlgorithmID;
+ Signature.KeySize = pKeyIn->KeySize;
+ Signature.HashAlgorithmID = pKeyIn->HashAlgorithmID;
+
+ if ((pKeyIn->EncryptAlgorithmID == PKCS1_v1_5_Ippcp) || (pKeyIn->EncryptAlgorithmID == PKCS1_v2_2_Ippcp))
+ {
+ if (SFs.pPKCS_DSA_Verify != NULL) // Verify signature if this function is supported
+ {
+ for (i=0; i < KeySizeInWords; i++)
+ {
+ Signature.Rsa.RSAModulus[i] = pKeyIn->Rsa.RSAModulus[i];
+ Signature.Rsa.RSAPublicExponent[i] = pKeyIn->Rsa.RSAPublicExponent[i];
+ Signature.Rsa.RSADigS[i] = pSignatureIn[i];
+ }
+ Buffer = malloc(ALIGN_UP(DATABUFFERSIZE, DCACHE_LINE_SIZE));
+ if (Buffer) {
+ AlignedBuffer = ALIGN_UP((UINT_T)Buffer, DCACHE_LINE_SIZE);
+ Retval = SFs.pPKCS_DSA_Verify(pBufferToVerifyIn, NumBytesToVerify, pSignature, AlignedBuffer);
+ free(Buffer);
+ } else {
+ return HeapExhaustedError;
+ }
+ }
+ else // Else, return not supported error
+ {
+ return SecurityFunctionNotSupported;
+ }
+ }
+#if ECDSA_SUPPORTED
+ else if ((pKeyIn->EncryptAlgorithmID == ECDSA_256) || (pKeyIn->EncryptAlgorithmID == ECDSA_521))
+ {
+ if (SFs.pECCP_DSA_Verify != NULL) // Verify signature if this function is supported
+ {
+ for (i=0; i < KeySizeInWords; i++)
+ {
+ Signature.Ecdsa.ECDSAPublicKeyCompX[i] = pKeyIn->Ecdsa.PublicKeyCompX[i];
+ Signature.Ecdsa.ECDSAPublicKeyCompY[i] = pKeyIn->Ecdsa.PublicKeyCompY[i];
+ Signature.Ecdsa.ECDSADigS_R[i] = pSignatureIn[i];
+ Signature.Ecdsa.ECDSADigS_S[i] = pSignatureIn[MAXECCKEYSIZEWORDS+i];
+ }
+ Retval = SFs.pECCP_DSA_Verify(pBufferToVerifyIn, NumBytesToVerify, pSignature, pECDSA_DataBuffer);
+ }
+ else // Else, return not supported error
+ {
+ return SecurityFunctionNotSupported;
+ }
+ }
+#endif
+ else {
+ return InvalidDSAError;
+ }
+
+ return Retval;
+}
+
+
+/******************** ValidateImage ******************************************************
+* Validate the Image based on a Hash passed in for the TIM or the hash for individual images
+* can be determined from IMAGE_INFO structure.
+*
+********************************************************************************************/
+UINT_T ValidateImage(UINT_T ImageAddr, UINT_T ImageID, pTIM pTIM_h)
+{
+ UINT_T Retval = NoError;
+ UINT_T HashSize = 0;
+ UINT_T i, ImageSize, HashAlgorithmID;
+ UINT_T *Buffer = NULL;
+ UINT_T *CalculatedHash;//Contains 16 32-bit words
+ UINT_T HashInTIM[WordLengthOf_SHA512]; // Contains 16 32-bit words
+ UINT_T ImageType;
+
+
+ pIMAGE_INFO_3_4_0 pImageInfo = NULL;
+ pImageInfo = FindImageInTIM(pTIM_h, ImageID);
+ if (pImageInfo == NULL)
+ return NoError; // return no error if not tim included
+
+ // If (TRUSTED TIM) or (TRUSTED FUSE BIT is set)
+ if (pTIM_h->pConsTIM->VersionBind.Trusted)
+ {
+ // If we are trying to Validate the TIM, it requires checking the DS. Special method to do that.
+ if ((pImageInfo->ImageID == TIMIDENTIFIER) || (pImageInfo->ImageID == NONTZDTIMID) )
+ {
+ Retval = ValidateTIMSignature(pTIM_h);
+ if (Retval != NoError)
+ return InvalidTIMImageError;
+ else
+ return Retval;
+ }
+ }
+
+ // First get relavant image data.
+ ImageSize = pImageInfo->ImageSize;
+ HashSize = pImageInfo->ImageSizeToHash;
+ HashAlgorithmID = pImageInfo->HashAlgorithmID;
+
+ // Make sure we got an expected HashAlgorithmID
+ switch (HashAlgorithmID)
+ {
+ case SHA160:
+ case SHA256:
+ case SHA512:
+ break;
+ default:
+ return InvalidSecureBootMethodError;
+ }
+
+ ImageType = pImageInfo->PartitionNumber.bits.ImageType;
+
+ switch(ImageType) {
+ case DLCMD_LZMA_IMAGE_TYPE:
+ case DLCMD_LZMA2_IMAGE_TYPE:
+ case DLCMD_YAFFS_LZMA_IMAGE_TYPE:
+ case DLCMD_UBIFS_LZMA_IMAGE_TYPE:
+ case DLCMD_JFFS2_LZMA_IMAGE_TYPE:
+ case DLCMD_RAW_LZMA_IMAGE_TYPE:
+ case DLCMD_IMG_LZMA_IMAGE_TYPE:
+ case DLCMD_IMG_MXZ_IMAGE_TYPE:
+ break;
+ default:
+ if(ImageSize < HashSize)
+ return (HashSizeMismatch);
+ }
+
+ if( HashSize == 0 )
+ return NoError;
+
+ // Read the image hash into a local variable.
+ for (i = 0; i < (HashAlgorithmID / 4); i++)
+ {
+ HashInTIM[i] = pImageInfo->Hash[i]; // Save the actual hash value
+ }
+
+ // If the image that will be validated is the TIM itself, we
+ // need to sample the TIM.bin hash out of the TIM image struct
+ // and fill it with zeroes so that we can compute the correct
+ // hash again.
+ if ( (pImageInfo->ImageID == TIMIDENTIFIER) || (pImageInfo->ImageID == NONTZDTIMID) )
+ {
+ for (i = 0; i < (HashAlgorithmID / 4); i++)
+ {
+ pImageInfo->Hash[i] = 0x0; // Overwrite the actual hash value with zeroes.
+ }
+ }
+
+ Buffer = malloc(ALIGN_UP((WordLengthOf_SHA256 << 2), DCACHE_LINE_SIZE));
+ if (Buffer == NULL) {
+ return HeapExhaustedError;
+ }
+ CalculatedHash = ALIGN_UP((UINT_T)Buffer, DCACHE_LINE_SIZE);
+
+ // If HASHing is supported, compute the hash
+ if (SFs.pSHAMessageDigest != NULL)
+ {
+ Retval = SFs.pSHAMessageDigest((UINT8_T*)ImageAddr, HashSize, (UINT8_T*) CalculatedHash, (HASHALGORITHMID_T) HashAlgorithmID);
+ }
+ else // Else, return not supported error
+ {
+ free(Buffer);
+ return SecurityFunctionNotSupported;
+ }
+
+ // Write back the hash value to the hash field of the TIM image.
+ if ( (pImageInfo->ImageID == TIMIDENTIFIER) || (pImageInfo->ImageID == NONTZDTIMID) )
+ {
+ for (i = 0; i < (HashAlgorithmID / 4); i++)
+ {
+ pImageInfo->Hash[i] = HashInTIM[i]; // Write the hash values back.
+ }
+ }
+
+ // Check the return value coming from the SHAMessageDigest function.
+ // If there is an error, return with this error code.
+ if (Retval != NoError) {
+ free(Buffer);
+ return Retval;
+ }
+
+ // Compare the 2 hashes
+ for (i = 0; i < (HashAlgorithmID / 4); i++)
+ {
+ if (HashInTIM[i] != CalculatedHash[i]) {
+ free(Buffer);
+ return (InvalidImageHash);
+ }
+ }
+
+ free(Buffer);
+ return Retval;
+}
+
+UINT_T ValidateImageSDTim(UINT_T ImageAddr, UINT_T ImageID, pTIM pDTIM, pTIM pTIM_h)
+{
+#ifdef CONFIG_ASR_SDTIM
+ UINT_T Retval = NoError;
+ pTIM pSDTIM_h = NULL;
+ pIMAGE_INFO_3_4_0 pImageInfo = NULL;
+ pIMAGE_INFO_3_4_0 pSdtimInfo = NULL;
+ UINT_T SecCfg = 0;
+
+ pImageInfo = FindImageInTIM(pDTIM, ImageID);
+ if (pImageInfo == NULL)
+ return NoError; // return no error if not tim included
+
+ if(!ImageIsSDTIMIncluded(pImageInfo))
+ return ValidateImage(ImageAddr, ImageID, pDTIM);
+
+ pSDTIM_h = malloc(sizeof(TIM));
+ if(pSDTIM_h == NULL)
+ return HeapExhaustedError;
+
+ Retval = SetTIMPointers(ImageAddr, pSDTIM_h);
+ if(Retval) {
+ free(pSDTIM_h);
+ return InvalidTIMImageError;
+ }
+
+ pSdtimInfo = FindImageInTIM(pSDTIM_h, SDTIM);
+ if(pSdtimInfo == NULL) {
+ free(pSDTIM_h);
+ return TIMNotFound;
+ }
+
+ SecCfg = GetSDTimSecureConfig(pSdtimInfo);
+ if(SecCfg == 0) {
+ free(pSDTIM_h);
+ return NoError;
+ }
+
+ Retval = ValiateDTIM(pSDTIM_h, pTIM_h);
+ if(Retval != NoError) {
+ free(pSDTIM_h);
+ return Retval;
+ }
+
+ ImageAddr += GetSDTimSpaceSize(pSdtimInfo);
+ Retval = ValidateImage(ImageAddr, ImageID, pSDTIM_h);
+ free(pSDTIM_h);
+
+ return Retval;
+#else
+ (VOID)pTIM_h;
+ return ValidateImage(ImageAddr, ImageID, pDTIM);
+#endif
+}
+
+#if TRUSTED
+/******************** VerifyPlatformKey *********************************************************
+* Verify that the hash of the keys stored in this Digital Signature match what's burned on the processor
+************************************************************************************************/
+UINT_T VerifyPlatformKey (pTIM pTIM_h)
+{
+ UINT_T Retval = NoError;
+ UINT_T FusedOEMKeyHash[WordLengthOf_SHA256];
+ UINT_T zero[WordLengthOf_SHA256];
+ UINT_T HashDataSizeInBytes, KeySizeInWords;
+ UINT_T KeyData[BINDKEYSIZE] = {0};
+ CHAR *Buffer = NULL;
+ UINT_T *CalculatedHash; // Contains 8 words
+ UINT_T i;
+
+ memset(zero, 0, ByteLengthOf_SHA256); //clear out 32 bytes
+
+ // Read out the fuse hashes
+ Retval = ReadOemHashKeyFuseBits(FusedOEMKeyHash, ByteLengthOf_SHA256 );
+ if (Retval != NoError)
+ return Retval;
+
+ if (memcmp(zero, FusedOEMKeyHash, ByteLengthOf_SHA256) == 0) // No OEM key Hash is burnt, just return NoError
+ return NoError;
+
+ switch (pTIM_h->pTBTIM_DS->DSAlgorithmID)
+ {
+ case PKCS1_v1_5_Ippcp:
+#if ECDSA_SUPPORTED
+ case ECDSA_256:
+ case ECDSA_521:
+#endif
+ case PKCS1_v2_2_Ippcp:
+ break;
+ default:
+ return InvalidSecureBootMethodError;
+ }
+
+ switch (pTIM_h->pTBTIM_DS->HashAlgorithmID)
+ {
+ case SHA160:
+ case SHA256:
+ case SHA512:
+ break;
+ default:
+ return InvalidSecureBootMethodError;
+ }
+
+ KeySizeInWords = (pTIM_h->pTBTIM_DS->KeySize==521)?17:pTIM_h->pTBTIM_DS->KeySize/32; // Convert Bits to Words
+
+ if (pTIM_h->pConsTIM->VersionBind.Version >= (TIM_3_4_00))
+ HashDataSizeInBytes = (KeySizeInWords*2 + 1) * 4; // (crypto_scheme||modulus-or-X||exponent-or-Y) in bytes (*4)
+ else
+ HashDataSizeInBytes = KeySizeInWords *4*2; // (exponent-or-X||modulus-or-Y) in bytes (*4)
+
+
+ // If LONG_KEYS == 1, hash algorithm has to be SHA512
+ //if ( (pFuses->bits.LongKeys == LONGKEYSENABLED) && (pTIM_h->pTBTIM_DS->HashAlgorithmID != SHA512) )
+ // return InvalidKeyHashError;
+
+
+ // Prepare the KeyData to calculate Hash of the Keys
+ if ((pTIM_h->pTBTIM_DS->DSAlgorithmID == PKCS1_v1_5_Ippcp) || (pTIM_h->pTBTIM_DS->DSAlgorithmID == PKCS1_v2_2_Ippcp))
+ {
+
+ if (pTIM_h->pConsTIM->VersionBind.Version >= (TIM_3_4_00)) {
+
+ // 1) Pack the crypto_scheme
+ //crypto_scheme: 0x0000A100 PKCSv1_SHA1_1024RSA
+ // 0x0000A110 PKCSv1_SHA256_1024RSA
+ // 0x0000A200 PKCSv1_SHA1_2048RSA
+ // 0x0000A210 PKCSv1_SHA256_2048RSA
+ // 0x0000A300 PKCSv1_PSS_SHA1_1024RSA
+ // 0x0000A310 PKCSv1_PSS_SHA256_1024RSA
+ // 0x0000A400 PKCSv1_PSS_SHA1_2048RSA
+ // 0x0000A410 PKCSv1_PSS_SHA256_2048RSA
+ if(pTIM_h->pTBTIM_DS->HashAlgorithmID == SHA256)
+ {
+ if (pTIM_h->pTBTIM_DS->DSAlgorithmID == PKCS1_v1_5_Ippcp)
+ KeyData[0] = (KeySizeInWords == 64) ? PKCSv1_SHA256_2048RSA : PKCSv1_SHA256_1024RSA;
+ else if (pTIM_h->pTBTIM_DS->DSAlgorithmID == PKCS1_v2_2_Ippcp)
+ KeyData[0] = (KeySizeInWords == 64) ? PKCSv1_PSS_SHA256_2048RSA : PKCSv1_PSS_SHA256_1024RSA;
+ }
+ else // Defaults to 160
+ {
+ if (pTIM_h->pTBTIM_DS->DSAlgorithmID == PKCS1_v1_5_Ippcp)
+ KeyData[0] = (KeySizeInWords == 64) ? PKCSv1_SHA1_2048RSA : PKCSv1_SHA1_1024RSA;
+ else if (pTIM_h->pTBTIM_DS->DSAlgorithmID == PKCS1_v2_2_Ippcp)
+ KeyData[0] = (KeySizeInWords == 64) ? PKCSv1_PSS_SHA1_2048RSA : PKCSv1_PSS_SHA1_1024RSA;
+ }
+
+ // 2) Pack the Modulus and Exponent
+ for (i=0; i < KeySizeInWords; i++)
+ {
+ KeyData[i+1] = pTIM_h->pTBTIM_DS->Rsa.RSAModulus[i];
+ KeyData[i+KeySizeInWords+1] = pTIM_h->pTBTIM_DS->Rsa.RSAPublicExponent[i];
+ }
+ }
+ else { // DO NOT include crypto_scheme and DO NOT swap exponent and modulus !!!
+ // Pack the Exponent and Modulus
+ for (i=0; i < KeySizeInWords; i++)
+ {
+ KeyData[i] = pTIM_h->pTBTIM_DS->Rsa.RSAPublicExponent[i];
+ KeyData[i+KeySizeInWords] = pTIM_h->pTBTIM_DS->Rsa.RSAModulus[i];
+ }
+ }
+ }
+#if ECDSA_SUPPORTED
+ else // ECDSA
+ {
+ if (pTIM_h->pConsTIM->VersionBind.Version >= (TIM_3_4_00)) {
+ // 1) Pack the crypto_scheme
+ //crypto_scheme: 0x0000B101 ECCP256_FIPS_DSA_SHA1
+ // 0x0000B111 ECCP256_FIPS_DSA_SHA256
+ // 0x0000B141 ECCP256_FIPS_DSA_SHA512
+ // 0x0000B301 ECCP521_FIPS_DSA_SHA1
+ // 0x0000B311 ECCP521_FIPS_DSA_SHA256
+ // 0x0000B341 ECCP521_FIPS_DSA_SHA512
+ if(pTIM_h->pTBTIM_DS->HashAlgorithmID == SHA512)
+ KeyData[0] = (KeySizeInWords == 17) ? ECCP521_FIPS_DSA_SHA512 : ECCP256_FIPS_DSA_SHA512;
+ else if(pTIM_h->pTBTIM_DS->HashAlgorithmID == SHA256)
+ KeyData[0] = (KeySizeInWords == 17) ? ECCP521_FIPS_DSA_SHA256 : ECCP256_FIPS_DSA_SHA256;
+ else // Defaults to 160
+ KeyData[0] = (KeySizeInWords == 17) ? ECCP521_FIPS_DSA_SHA1 : ECCP256_FIPS_DSA_SHA1;
+
+ // 2) Pack the X-coordinate and Y-coordinate
+ for (i=0; i < KeySizeInWords; i++)
+ {
+ KeyData[i+1] = pTIM_h->pTBTIM_DS->Ecdsa.ECDSAPublicKeyCompX[i];
+ KeyData[i+KeySizeInWords+1] = pTIM_h->pTBTIM_DS->Ecdsa.ECDSAPublicKeyCompY[i];
+ }
+ }
+ else { // DO NOT include crypto_scheme !!!
+ // Pack the X-coordinate and Y-coordinate
+ for (i=0; i < KeySizeInWords; i++)
+ {
+ KeyData[i] = pTIM_h->pTBTIM_DS->Ecdsa.ECDSAPublicKeyCompX[i];
+ KeyData[i+KeySizeInWords] = pTIM_h->pTBTIM_DS->Ecdsa.ECDSAPublicKeyCompY[i];
+ }
+ }
+ }
+#endif
+
+ //Key Padding is on by default
+ HashDataSizeInBytes = BINDKEYSIZE*4; // MaxKeySize*2+CryptoScheme in Bytes: 129*4 = 516
+
+ Buffer = malloc(ALIGN_UP((WordLengthOf_SHA256 << 2), DCACHE_LINE_SIZE));
+ if (Buffer == NULL) {
+ return HeapExhaustedError;
+ }
+ CalculatedHash = ALIGN_UP((UINT_T)Buffer, DCACHE_LINE_SIZE);
+
+ // Do the SHA Hash
+ Retval = SFs.pSHAMessageDigest((unsigned char *)KeyData, HashDataSizeInBytes,
+ (unsigned char *)CalculatedHash,
+ (HASHALGORITHMID_T) pTIM_h->pTBTIM_DS->HashAlgorithmID);
+
+ if (Retval != NoError){
+ free(Buffer);
+ return Retval;
+ }
+
+ // Compare Hash of the Keys from the TIM vs. what's stored in the fuses.
+ for (i = 0; i < (pTIM_h->pTBTIM_DS->HashAlgorithmID / 4); i++)
+ {
+ if (CalculatedHash[i] != FusedOEMKeyHash[i]) {
+ free(Buffer);
+ return (InvalidOTPHashError);
+ }
+ }
+
+ free(Buffer);
+ return Retval;
+}
+
+/******************** ValidateKeyHashes ******************************************************
+* Validate the Keys based on a OTP Hash passed or from the Hash stored in TIM
+* If the OEM keys are being verified (TIMIDENTIFIER) do the platform verify PI as well
+********************************************************************************************/
+UINT_T VerifyKey(KEYMODULES_T KeyType, pTIM pTIM_h)
+{
+ UINT_T Retval = NoError;
+
+ // Check if we are to Perform Platform Verification.
+ if (KeyType == PlatformVerificationKey)
+ Retval = VerifyPlatformKey(pTIM_h);
+
+ // TBD Add support to verify other keys as well as needed.
+
+ return Retval;
+}
+
+/******************** CalcBufferHash ******************************************************
+* Calc the Hash of Input Buffer, Not Useds
+********************************************************************************************/
+INT_T CalcBufferHash(UINT_T *Buffer, UINT_T NumBytesToHash, UINT_T *HashBuff, HASHALGORITHMID_T HashType)
+{
+ UINT_T Retval = NoError;
+ switch (HashType)
+ {
+ case SHA160:
+ case SHA256:
+ case SHA512:
+ break;
+ default:
+ return InvalidSecureBootMethodError;
+ }
+ Retval = SFs.pSHAMessageDigest((UINT8_T*)Buffer, NumBytesToHash, (UINT8_T*) HashBuff, HashType);
+
+ return Retval;
+}
+
+/******************** VerifyBufferHash ******************************************************
+* Verify the Hash of Input Buffer, Not Used
+********************************************************************************************/
+UINT_T VerifyBufferHash(UINT_T BufferAddr, UINT_T NumBytesToVerify, HASHALGORITHMID_T HashType, const UINT_T * pHashValueIn)
+{
+ UINT_T Retval, i;
+ UINT_T CalculatedHash[WordLengthOf_SHA512]; // Contains 16 32-bit words
+
+ if( NumBytesToVerify == 0 )
+ return NoError;
+
+ switch (HashType)
+ {
+ case SHA160:
+ case SHA256:
+ case SHA512:
+ break;
+ default:
+ return InvalidSecureBootMethodError;
+ }
+
+
+ // Compute the hash
+ Retval = SFs.pSHAMessageDigest((UINT8_T*)BufferAddr, NumBytesToVerify, (UINT8_T*) CalculatedHash, HashType);
+
+ // Check the return value coming from the SHAMessageDigest function.
+ // If there is an error, return with this error code.
+ if (Retval != NoError)
+ return Retval;
+
+ // Compare the 2 hashes
+ for (i = 0; i < (HashType / 4); i++)
+ {
+ if (pHashValueIn[i] != CalculatedHash[i])
+ return (InvalidImageHash);
+ }
+
+ return NoError;
+}
+
+#endif //BOOTROM
+
+
+#if !BOOTROM // BootLoader Only
+/******************** VerifyEncryptedKey ***************************************************
+* Verify the Signature of Encrypted Key
+********************************************************************************************/
+UINT_T VerifyEncryptedKey(pKEY_MOD_3_4_0 PlainTextKey, pKEY_MOD_3_4_0 EncryptedKey, pKEY_MOD_3_4_0 DecryptionKey)
+{
+ UINT_T Retval = NoError;
+
+ if ((DecryptionKey->EncryptAlgorithmID == PKCS1_v1_5_Ippcp) || (DecryptionKey->EncryptAlgorithmID == PKCS1_v2_2_Ippcp))
+ {
+ // First verify the signature of the public exponent
+ Retval = VerifySignature((UINT8_T*) PlainTextKey->Rsa.RSAPublicExponent, (PlainTextKey->KeySize)/8, (UINT_T*) EncryptedKey->EncryptedRsa.EncryptedHashRSAPublicExponent, DecryptionKey, 0);
+ if (Retval != NoError) // Signature of the exponent is NOT valid
+ {
+ return Retval;
+ }
+ else // Signature of the exponent is valid
+ {
+ // Verify the signature of the public modulus
+ Retval = VerifySignature((UINT8_T*) PlainTextKey->Rsa.RSAModulus, (PlainTextKey->KeySize)/8, (UINT_T*) EncryptedKey->EncryptedRsa.EncryptedHashRSAModulus, DecryptionKey, 0);
+ }
+ }
+#if ECDSA_SUPPORTED
+ else if ((DecryptionKey->EncryptAlgorithmID == ECDSA_256) || (DecryptionKey->EncryptAlgorithmID == ECDSA_521))
+ {
+ // First verify the signature of the X component
+ Retval = VerifySignature((UINT8_T*) PlainTextKey->Ecdsa.PublicKeyCompX, ((PlainTextKey->KeySize+31)/32)*4, (UINT_T*) EncryptedKey->EncryptedEcdsa.EncryptedHashPublicKeyCompX_R, DecryptionKey, 0);
+ if (Retval != NoError) // Signature of the X component is NOT valid
+ {
+ return Retval;
+ }
+ else // Signature of the X component is valid
+ {
+ // Verify the signature of the Y component
+ Retval = VerifySignature((UINT8_T*) PlainTextKey->Ecdsa.PublicKeyCompY, ((PlainTextKey->KeySize+31)/32)*4, (UINT_T*) EncryptedKey->EncryptedEcdsa.EncryptedHashPublicKeyCompY_R, DecryptionKey, 0);
+ }
+ }
+#endif
+ else
+ return InvalidEncAlgorithmID;
+ return Retval;
+}
+
+#endif // #if !BOOTROM