
  /*
   *  Object %    : %
   *  State           :  %state%
   *  Creation date   :  Mon Nov 29 14:10:40 2004
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief A brief description of this module
   *
   *  \version SecureBootMainNor.c#1:csrc:4
   *  \author adams
   *  \remarks Copyright (C) 2004 by Discretix Technologies Ltd.
   *           All Rights reserved
   */



/************* Include Files ****************/

#include "DX_VOS_BaseTypes.h"
#include "error.h"
#include "DX_SecureBoot.h"
#include "GeneralHwDefs.h"
#include "MNG_Functions.h"
#include "CRYS_RSA_Types.h"
#include "CRYS_RSA_BUILD.h"
#include "CRYS_RSA_SCHEMES.h"
#include "SEC_BOOT_util.h"
#include "SEC_BOOT_flash.h"

/************************ Defines ******************************/

/************************ Enums ******************************/


/************************ Typedefs ******************************/


/************************ Global Data ******************************/

/************* Private function prototype ****************/

/**
 * @brief The ExecuteHashOnFlashDataBlock function executes a HASH on a block of ram in the FLASH.
 *
 *        This function overides the RAM !!! - all data is overruned.
 *
 *        The function operates the follwing steps:
 *         
 *
 */                              
void ExecuteHashOnFlashDataBlock( DxUint32_t FlashAddr,
                                  DxInt32_t  SizeInWords,
                                  DxUint32_t *WorkRam_ptr,
                                  HASH_Result_t HashResult )
{

   /* LOCAL DECLERATIONS */
   
   CRYS_HASH_Result_t CrysHashResult;
   WorkRam_ptr = WorkRam_ptr;
    
   /* FUNCTION LOGIC */
      
   /* calculate the HASH */
   CRYS_HASH  ( CRYS_HASH_SHA256_mode,
                (DxUint8_t *)FlashAddr,
                SizeInWords * sizeof(DxUint32_t),
                CrysHashResult );
                
   /* copy the result */
   UTIL_MemCopy( (DxUint8_t*)HashResult , (DxUint8_t*)CrysHashResult , sizeof(HASH_Result_t ));            
                 
   return;

}/* END OF ExecuteHashOnFlashDataBlock */                                   
             

/************************ Public Functions ******************************/

/**
 * @brief The DX_SecureBoot function executes the secured boot process.
 *
 *        The function operates the follwing steps:
 *         
 *
 */                              
DX_Error_t DX_SecureBoot ( DxUint32_t VrlPrimaryOffsetAddr,
                           void (*GetFlashData)(DxUint32_t *,DxUint32_t,DxUint32_t),
                           DxUint32_t *N_ptr,
                           DxUint32_t Index,
                           DxUint32_t *FlashBaseAddr_ptr )
{
   /* LOCAL DECLERATIONS */
         
   /* the VRL header data ( primary and secondary ) */
   VRL_Header_t VrlPrimaryHeader;    
   VRL_Header_t VrlSecondaryHeader;
   
   /* a pointer to the signature struct on the VRL */  
   VRL_Sign_t   *VRL_Sign_ptr;
   
   /* a pointer to the secondary info struct on the VRL */
   VRL_SecondaryInfo_t *VRL_SecondaryInfo_ptr;
   
   /* The VRL record info */
   VRL_RecordInfo_t VRL_CurrentRecordInfo;
   
   /* a HASH result variable */
   HASH_Result_t HashResult;
   
   /* a result variable */
   DxUint32_t result;
   
   /* current record address - the current record address on the VRL */
   DxUint32_t VrlCurrentRecordAddr;
   
   /* a variable to examine the number of records left to examine */
   DxUint32_t NumOfRecordsLeftToExamine;
   
   /* the record counter */
   DxInt32_t RecordCounter;
      
   /* table index variable : 0 - primary , 1 - secondary */
   DxUint32_t VRL_tableIdx;
   
   /* the work flash address */
   DxUint32_t *WorkRam_ptr,*WorkRam1_ptr;
    
   /* VRL base addr */
   DxUint32_t VrlBaseAddr;
   
   /* error code */
   DX_Error_t Error;
   
   /* public key context */
   CRYS_RSAUserPubKey_t PubKey;
   
   /* the public exponent */
   DxUint8_t E[3]= { 0x1 , 0x0 , 0x1 };
   
   /* a buffer for calcualting reversed info from the VRL */
   DxUint32_t Buff[RSA_MOD_SIZE_IN_WORDS];
        
   /* FUNCTION LOGIC */

   /* ............ STEP 1 : validating and building the pub key object ..................................... */
   /* ---------------------------------------------------------------------------------- */ 

   
    /* reverse the value of N ( to the RSA format ) */
    UTIL_MemCopy( (DxUint8_t*)Buff , (DxUint8_t*)N_ptr , RSA_MOD_SIZE_IN_BYTES );
    UTIL_ReverseBuff( (DxUint8_t*)Buff , RSA_MOD_SIZE_IN_BYTES );

    Error = DX_MNG_RSA_BuildPlatformPubKey( 1, /* OEM */
                                            Index, 
                                            &PubKey,
                                            (DxUint8_t*)E,					
                                            3,
                                 		    RSA_MOD_SIZE_IN_BYTES,
                                            (DxUint8_t*)Buff);
    
    /* on failure return an error */
    if( Error != DX_OK )
    { 
        return DX_PUB_KEY_HASH_VALIDATION_FAILURE;
    } 
    
   /* ............ STEP 2 : checking the VRL magic number and integrity ............... */
   /* --------------------------------------------------------------------------------- */

   /* load the VRL header from the flash */
   WorkRam_ptr = FlashBaseAddr_ptr + (VrlPrimaryOffsetAddr/sizeof(DxUint32_t));
                    
   /* copy the result to the variable */
   UTIL_MemCopy( (DxUint8_t*)&VrlPrimaryHeader , (DxUint8_t*)WorkRam_ptr , sizeof(VRL_Header_t) );
              
   /* check if the magic number is valid */
   if( VrlPrimaryHeader.MagicNumber != VRL_MAGIC_NUMBER )
   
     return DX_INVALID_PRIMARY_VRL_MAGIC_NUM_VAL;
             
   /* .......... check the primary VRL integrity */   
   
   /* calc the VRL HASH according to the length minus the signitiure size - mod size */
   ExecuteHashOnFlashDataBlock( (DxUint32_t)WorkRam_ptr,
                                VrlPrimaryHeader.LenInWords - (RSA_MOD_SIZE_IN_BYTES/sizeof(DxUint32_t)),
                                DX_NULL,
                                HashResult);
                                
   /* load H and the signature to the RAM */
   WorkRam_ptr = FlashBaseAddr_ptr + 
                  (VrlPrimaryOffsetAddr + (VrlPrimaryHeader.LenInWords)*sizeof(DxUint32_t) - sizeof(VRL_Sign_t))/sizeof(DxUint32_t);   
   
   /* call the verify function */ 
   VRL_Sign_ptr = (VRL_Sign_t*)WorkRam_ptr; 

   /* reverse the value of signiture ( to the RSA format ) */
   UTIL_MemCopy( (DxUint8_t*)Buff , (DxUint8_t*)VRL_Sign_ptr->sig , RSA_MOD_SIZE_IN_BYTES );
   UTIL_ReverseBuff( (DxUint8_t*)Buff , RSA_MOD_SIZE_IN_BYTES );
    
   result = CRYS_RSA_PSS_SHA256_Verify((CRYS_RSAPubUserContext_t*)DX_NULL,&PubKey,CRYS_PKCS1_MGF1,CRYS_RSA_VERIFY_SALT_LENGTH_UNKNOWN,(DxUint8_t*)HashResult,(DxUint8_t*)Buff);
   
   /* on failure exit with an error code */
   if( result )
   { 
     return DX_VRL_PRIMARY_INTEGRITY_FAILURE;
   }
     
   /* ........... check the secondary VRL integrity ................... */
   
   /* if the secondary VRL exists check its validity */
   if( VrlPrimaryHeader.SecondaryVrlPresent == DX_TRUE )
   {  
      /* set the VRL secondary header from the flash */
      WorkRam_ptr = FlashBaseAddr_ptr + (VrlPrimaryHeader.SecondaryVrlAddr / sizeof(DxUint32_t)); 
                 
      /* copy the result to the variable */
      UTIL_MemCopy( (DxUint8_t*)&VrlSecondaryHeader , (DxUint8_t*)WorkRam_ptr , sizeof(VRL_Header_t) );
              
      /* check if the magic number is valid */
      if( VrlSecondaryHeader.MagicNumber != VRL_MAGIC_NUMBER )
      {
         return DX_INVALID_SECONDARY_VRL_MAGIC_NUM_VAL;
      }   
       
      /* calc the VRL HASH according to the length minus the signitiure size - mod size */
      ExecuteHashOnFlashDataBlock( (DxUint32_t)(FlashBaseAddr_ptr + (VrlPrimaryHeader.SecondaryVrlAddr)/sizeof(DxUint32_t)),
                                   VrlSecondaryHeader.LenInWords - (RSA_MOD_SIZE_IN_BYTES/sizeof(DxUint32_t)),
                                   DX_NULL,
                                   HashResult);  

      /* set H and the signature to the RAM */
      WorkRam_ptr = FlashBaseAddr_ptr + 
         (VrlPrimaryHeader.SecondaryVrlAddr + (VrlSecondaryHeader.LenInWords)*sizeof(DxUint32_t) - sizeof(VRL_Sign_t))/sizeof(DxUint32_t);      
       
      /* load N to the RAM */
      WorkRam1_ptr = FlashBaseAddr_ptr + 
         (VrlPrimaryOffsetAddr + (VrlPrimaryHeader.LenInWords)*sizeof(DxUint32_t) - sizeof(VRL_Sign_t) - sizeof(VRL_SecondaryInfo_t))/sizeof(DxUint32_t);
                
      /* call the verify function */   
      VRL_Sign_ptr = (VRL_Sign_t*)WorkRam_ptr;
      VRL_SecondaryInfo_ptr = (VRL_SecondaryInfo_t *)WorkRam1_ptr;

      /* reverse the value of N ( to the RSA format ) */
      UTIL_MemCopy( (DxUint8_t*)Buff , (DxUint8_t*)VRL_SecondaryInfo_ptr->N , RSA_MOD_SIZE_IN_BYTES );
      UTIL_ReverseBuff( (DxUint8_t*)Buff , RSA_MOD_SIZE_IN_BYTES );

      CRYS_RSA_Build_PubKey(  &PubKey,
                              (DxUint8_t*)&E,					
                              3,
                              (DxUint8_t*)Buff,
                              RSA_MOD_SIZE_IN_BYTES);
      
      /* reverse the value of signiture ( to the RSA format ) */
      UTIL_MemCopy( (DxUint8_t*)Buff , (DxUint8_t*)VRL_Sign_ptr->sig , RSA_MOD_SIZE_IN_BYTES );
      UTIL_ReverseBuff( (DxUint8_t*)Buff , RSA_MOD_SIZE_IN_BYTES );

      result = CRYS_RSA_PSS_SHA256_Verify((CRYS_RSAPubUserContext_t*)DX_NULL,&PubKey,CRYS_PKCS1_MGF1,CRYS_RSA_VERIFY_SALT_LENGTH_UNKNOWN,(DxUint8_t*)HashResult,(DxUint8_t*)Buff);
    
      /* on failure exit with an error code */
      if( !result )
      {  
        return DX_VRL_SECONDARY_INTEGRITY_FAILURE;
      }
       
   }/* end of secondary integrity check */         
     
   /* ............ STEP 3 : checking the SW records integrity ......... */
   /* ----------------------------------------------------------------- */

   /* ****** for loop for handeling the SW integrity for the primary and secondary tables ****** */
   for( VRL_tableIdx = 0 ; VRL_tableIdx <= VrlPrimaryHeader.SecondaryVrlPresent ; VRL_tableIdx++ )
   {
     /* -------- initializing table identifiers */
     
     /* primary table case */
     if( VRL_tableIdx == 0 )
     {
       /* initialize the VRL index address */
       VrlCurrentRecordAddr = VrlPrimaryOffsetAddr + sizeof(VRL_Header_t);
   
       /* set the number of records to examin */
       NumOfRecordsLeftToExamine = VrlPrimaryHeader.NumOfRecords;
       
       /* set the VRL base address */
       VrlBaseAddr = VrlPrimaryOffsetAddr;
       
     }/* end of primary table case */  
     
     /* secondary table case */
     else
     {
       /* initialize the VRL index address */
       VrlCurrentRecordAddr = VrlPrimaryHeader.SecondaryVrlAddr + sizeof(VRL_Header_t);
   
       /* set the number of records to examin */
       NumOfRecordsLeftToExamine = VrlSecondaryHeader.NumOfRecords;
       
       /* set the VRL base address */
       VrlBaseAddr = VrlPrimaryHeader.SecondaryVrlAddr;
               
     }/* end of secondary table case */
   
     /* --------- common initializing variables - needed to be initialized before each while loop
                  for searching the records */
   
     /* initialize the record counter to -1 */
     RecordCounter = -1;
      
     /* do loop for examining all of the flash SW records */
     while( NumOfRecordsLeftToExamine )
     {
        /* set the current record */
        WorkRam_ptr = FlashBaseAddr_ptr + VrlCurrentRecordAddr / sizeof(DxUint32_t);
                                                
        /* save the record to the local structure */
        UTIL_MemCopy( (DxUint8_t*)&VRL_CurrentRecordInfo , (DxUint8_t*)WorkRam_ptr , sizeof(VRL_RecordInfo_t) );
      
        /* decrement the number of records to examine and increment the record num counter */
        NumOfRecordsLeftToExamine--;
      
        /* increment the record counter */
        RecordCounter++;
      
        /* increment the record address to the next record */
        VrlCurrentRecordAddr += sizeof(VRL_RecordInfo_t);
               
        /* calculate the HASH on the current block */   
        ExecuteHashOnFlashDataBlock( (DxUint32_t)(FlashBaseAddr_ptr + (VRL_CurrentRecordInfo.Addr + VrlBaseAddr)/sizeof(DxUint32_t) ),
                                     VRL_CurrentRecordInfo.LenInWords,
                                     WorkRam_ptr,
                                     HashResult);
      
        /* check the hash signiture of the current block */
        result = UTIL_MemCmp( (DxUint8_t*)VRL_CurrentRecordInfo.SwHashResult,(DxUint8_t*)HashResult,sizeof(HashResult) );
                                   
        /* if the HASH signiture doesnt match the resulr return error */
        if( !result )
        {
           return DX_RECORD_INTEGRITY_FAILURE(VRL_tableIdx,RecordCounter);                              
        }   
   
     }/* end of exaining the SW blocks */
     
   }/* end of examining primary and secondary tables loop */  

   /* closing the PIC clock */
                    
   return DX_OK;
   
}/* END OF DX_SecureBoot */                                           

