blob: 73b47b506ad856f663aecf590d31cdb5ddfe62a2 [file] [log] [blame]
/****************************************************************************
*
* (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