/** * @brief This function is responsible to change storage * addresses of the SW components in the VRL. * * @param[in] vrlPtr - a pointer to the VRL * @param[in] address - the address to insert into the VRL * @param[in] numOfAddressesInArray - number of addresses in the * previous array * * @return DxError_t - On success the value DX_OK is returned, * on failure - a value from BootImagesVerifier_error.h */ DxError_t DX_BIV_VRLChangeSwCompStoreAddr(DxUint32_t *vrlPtr, DxUint32_t adresses, DxUint32_t indexOfAddress) { /* temp vrl header */ VRL_Header_t *vrlHeaderPtr; /* number of SW components, offset to comps data */ DxUint32_t numOfComps = 0, offsetToSwCompsData = 0; /* temporary pointer to SW comps data */ VRL_ParamRecordInfo_t *swCompDataPtr; /* temp pointer to VRL */ DxUint32_t *tempVRLPtr = vrlPtr; /*------------------ CODE -------------------*/ /* Check inputs */ if (vrlPtr == DX_NULL){ DX_PAL_LOG_DEBUG("VRL ptr is NULL\n"); return DX_BOOT_IMG_VERIFIER_INV_INPUT_PARAM; } /* In case there is additional data - need to skip it */ #ifdef DX_SB_ADDITIONAL_DATA_SUPPORTED /* set the temporary address to after the additional data header */ tempVRLPtr = tempVRLPtr + ADDITIONAL_DATA_SIZE_IN_BYTES/sizeof(DxUint32_t); #endif /* parse the VRL to point to the storage addresses */ /*-------------------------------------------------*/ vrlHeaderPtr = (VRL_Header_t*)tempVRLPtr; /* Calculate the VRL size according to offset to signature + sec address + num of comps * (comps params) */ /*-------------------------------------------------------------------------------------------------------*/ /* Get the number of sw comnponents from the header vrlSize field */ numOfComps = (vrlHeaderPtr->vrlSize & VRL_LEN_NUM_OF_COMPS_BIT_MASK ) >> VRL_LEN_NUM_OF_COMPS_BIT_LOCATION; if (indexOfAddress > (numOfComps-1)) { DX_PAL_LOG_DEBUG("Invalid index\n"); return DX_BOOT_IMG_VERIFIER_INV_INPUT_PARAM; } offsetToSwCompsData = (DxUint32_t)(vrlHeaderPtr->vrlSize & VRL_LEN_SIGNATURE_OFFSET_BIT_MASK) /* signature offset */ + sizeof(VRL_Sign_t)/sizeof(DxUint32_t) /* signature */ + sizeof(VRL_SecAddress_t)/sizeof(DxUint32_t); /* secondary address */ /* Point to the SW comps data */ tempVRLPtr = tempVRLPtr + offsetToSwCompsData; /* Change the relevant address */ swCompDataPtr = (VRL_ParamRecordInfo_t*)(tempVRLPtr + indexOfAddress*sizeof(VRL_ParamRecordInfo_t)/sizeof(DxUint32_t)); swCompDataPtr->StoreAddr = adresses; return DX_OK; }/* End of DX_BIV_VRLChangeSwCompStoreAddr */
/*! * This function adds a completion report to the completion fifo. * * \param qid The queue id. * \param taskId Completion task ID as set by vTaskSetCurrentTaskTag(). * \param completionType COMPLETION_INTERNAL or COMPLETION_EXTERNAL. * \param axiWriteCount AXI transactions counter from previous completion report. */ void CompletionFifoInsert(int qid, uint32_t taskId, CompletionType_t *completionType, uint32_t axiWriteCount) { uint8_t fifoItem = 0; uint32_t fifoIdx; if (((CompletionType_t)completionType != COMPLETION_INTERNAL) && ((CompletionType_t)completionType != COMPLETION_EXTERNAL)) { DX_PAL_Abort("Bad completionType"); } if (taskId >= BITMASK(FIFO_TASK_ID_BIT_SIZE)) { DX_PAL_Abort("Bad completionTaskId"); } if (axiWriteCount >= BITMASK(FIFO_AXI_COUNTER_BIT_SIZE)) { DX_PAL_Abort("Bad axiWriteCount"); } if ((gCompletionFifoHead[qid] - gCompletionFifoTail[qid]) >= COMPLETION_FIFO_LEN) { DX_PAL_Abort("Completion FIFO overflow"); } SET_FIFO_COMPLETION_TYPE(fifoItem, (CompletionType_t)completionType); SET_FIFO_AXI_COUNTER(fifoItem, axiWriteCount); SET_FIFO_COMPLETION_TASK_ID(fifoItem, taskId); fifoIdx = gCompletionFifoHead[qid] & (COMPLETION_FIFO_LEN - 1); gCompletionFifo[qid][fifoIdx] = fifoItem; gCompletionFifoHead[qid]++; DX_PAL_LOG_DEBUG("qid=%d taskId=%d fifoIdx=%d gCompletionFifoHead[qid]=%d completionType=%s axiWriteCount=%d\n", (int)qid, (int)taskId, (int)fifoIdx, (int)gCompletionFifoHead[qid], ((CompletionType_t)completionType==COMPLETION_INTERNAL)?"INTERNAL":"EXTERNAL", (int)axiWriteCount); }
/*! * This function initializes the completion counter event, clears the * state structure and sets completion counter "0" as the first available * counter to be used when calling "AllocCounter". * * \return int one of the error codes defined in err.h */ int InitCompletionPlat(void) { uint8_t dummy; int qid; /* Clear completion fifo */ for ( qid=0; qid < MAX_NUM_HW_QUEUES; qid++ ) { /* Clear FIFO head/tail */ gCompletionFifoHead[qid] = 0; gCompletionFifoTail[qid] = 0; /* The global AXI write counter is reset only once */ gAxiWriteCompleted[qid] = 0; gCompletionCount[qid] = 0; gExpectedAxiWrites[qid] = 0; gCompletionCtx[qid] = COMPLETION_INVALID; DX_PAL_MemSetZero( gCompletionFifo, MAX_NUM_HW_QUEUES*COMPLETION_FIFO_LEN ); /* Clear all past AXI completion counters */ /* Actual bus values of AXI IDs for queues (0-3) DMA are 8, 9, A, B */ dummy = DX_HAL_ReadCcRegister(DX_CC_REG_OFFSET(CRY_KERNEL, AXIM_MON_COMP8) + QID_TO_AXI_ID(qid)*sizeof(uint32_t)); DX_PAL_LOG_DEBUG("Initial AXI_MON_COMP%d value=0x%08X\n", (int)qid, (unsigned int)dummy); dummy = dummy; /*avoid compiler warning*/ } return DX_RET_OK; }
static void InitCombinedContext( struct sep_ctx_combined *pCtx, CrysCombinedConfig_t *pConfig) { CrysCombinedEngineSource_e engineSrc = INPUT_NULL; enum sep_engine_type engineType = SEP_ENGINE_NULL; int engineIdx; int done = 0; /* set alg */ pCtx->alg = SEP_CRYPTO_ALG_COMBINED; pCtx->mode = 0; /* encode engines connections into SEP format */ for (engineIdx = 0; (engineIdx < CRYS_COMBINED_MAX_NODES) && (!done); engineIdx++) { if(pConfig->node[engineIdx].pContext) { /* set context's pointers */ pCtx->sub_ctx[engineIdx] = (struct sep_ctx_cache_entry *)DX_GetUserCtxLocation(pConfig->node[engineIdx].pContext); } else { pCtx->sub_ctx[engineIdx] = NULL; } /* set engine source */ engineSrc = CrysCombinedEngineSrcGet(pConfig, engineIdx); /* set engine type */ if (pCtx->sub_ctx[engineIdx] != NULL) { engineType = GetCryptoEngineType(pCtx->sub_ctx[engineIdx]->alg); } else if (engineSrc != INPUT_NULL) { /* incase engine source is not NULL and NULL sub-context is passed then DOUT is -DOUT */ engineType = SEP_ENGINE_DOUT; done = 1; /* do not allow to set DOUT twice! */ } else { /* both context pointer & input type are NULL -we're done */ engineType = SEP_ENGINE_NULL; done = 1; } SepCombinedEnginePropsSet(&pCtx->mode, engineIdx, engineSrc, engineType); DX_PAL_LOG_DEBUG("engineSrc=%d engineType=%d\n", engineSrc, engineType); } }
/** * @brief This function gets the index of the OTP in which the HASH of the public key resides. * * * @param[in] hwBaseAddress - base address for the CC HW engines * @param[in] indexInOTP - index in OTP in which the required HASH resides * @param[out] hashOutput - the HASH of the public key * @param[in] hashBufSize - the HASH buffer size in bytes * * @return DxError_t - On success the value DX_OK is returned, * on failure - a value from BootImagesVerifier_error.h */ DxError_t DX_BIV_GetPubKeyHASH(DxUint32_t hwBaseAddress, DxUint32_t indexInOTP, DxUint32_t *hashOutput, DxUint32_t hashBufSize) { DxError_t error = DX_OK; #ifdef BIG__ENDIAN DxUint32_t i; #endif /*------------------ CODE -------------------*/ /* Verify that the output buffer is in sufficient size */ if (hashBufSize < DX_SB_HASH_LENGTH_IN_WORDS* sizeof(DxUint32_t)){ DX_PAL_LOG_DEBUG("HASH buf too small\n"); return DX_BOOT_IMG_VERIFIER_HASH_BUF_TOO_SMALL; } /* Aquire control on the CC */ /*--------------------------*/ error = GEN_AcquireCCLock(hwBaseAddress); if (error != DX_OK) return error; /* Get the HASH from the SRAM */ /*----------------------------*/ error = NVM_ReadHASHPubKey(hwBaseAddress, indexInOTP, hashOutput); #ifdef BIG__ENDIAN for (i = 0; i < DX_SB_HASH_LENGTH_IN_WORDS; i++) { /* If in BIG__ENDIAN platforms revert the key (back to its original representation) */ UTIL_ReverseBuff( (DxUint8_t*)&hashOutput[i] , sizeof(DxUint32_t) ); } #endif /* Release control on the CC */ /*---------------------------*/ GEN_ReleaseCCLock(hwBaseAddress); return error; }
/** * @brief This function is responsible to verification of the VRL list. * The function will go over the VRL list starting from the first and verify it, in case * the verification fail, the function will go to the next VRL and verify it, till a suuccessfull * verification or the end of the list is reached. * The verification process verifies the following: * 1. The primary public key as saved in the VRL versus the HASHd public key that is saved in the NVM/OTP * 2. The RSA signature of the VRL * 3. The SW version that should be bigger than the SW minimum version as is saved in the NVM/OTP * 4. Each of the SW components HASH as appear in the VRL * * * @param[in] flashRead_func - User's Flash read function used to read data from the flash to memory location * @param[in] userContext - User's context for the usage of flashRead_func * @param[in] hwBaseAddress - base address for the CC HW engines * @param[in] vrlList - VRL list ordered, the first item will be the first to be verified * @param[in] numOfVrlInList - number of VRLs in the given list * @param[out] index_ptr - the index in the VRL list of the VRL that passed verification * @param[in] workspace_ptr - temporary buffer to load the VRL and SW components to * @param[in] workspaceSize - the temporary buffer size in bytes * * @return DxError_t - On success the value DX_OK is returned, * on failure - a value from BootImagesVerifier_error.h */ DxError_t DX_BIV_SwImageVerification(DX_SB_FlashRead flashRead_func, void *userContext, DxUint32_t hwBaseAddress, DX_BIM_VRL_TABLE_t vrlList, DxUint32_t numOfVrlInList, DxUint32_t *index_ptr, DxUint32_t *workspace_ptr, DxUint32_t workspaceSize) { /* error variable */ DxError_t error = DX_OK; /* internal index */ DxUint32_t i = 0; /* secondary N hash that is saved in the Primary VRL to be verified with the secondary N hash in secondary VRL */ DxUint32_t secondaryNHash[DX_SB_HASH_LENGTH_IN_WORDS]; /* s/w component data */ VRL_Parser_CompsData_t swCompsData; /* indicator if secondary vrl exists */ DxUint8_t isSecExist = 0; /* VRL info for secondary usage */ SW_Verification_Data_t secVrlData; /*------------------ CODE -------------------*/ /* Verify input parameters */ if (flashRead_func == DX_NULL){ DX_PAL_LOG_DEBUG("flashRead_func is NULL\n"); return DX_BOOT_IMG_VERIFIER_INV_INPUT_PARAM; } /* Verify vrlLis */ if (vrlList == DX_NULL || numOfVrlInList == 0){ DX_PAL_LOG_DEBUG("vrlList or numOfVrlInList are 0\n"); return DX_BOOT_IMG_VERIFIER_INV_INPUT_PARAM; } if (index_ptr == DX_NULL || workspace_ptr == DX_NULL || workspaceSize == 0){ DX_PAL_LOG_DEBUG("index_ptr || workspace_ptr || workspaceSize are zero\n"); return DX_BOOT_IMG_VERIFIER_INV_INPUT_PARAM; } /* aquire control on the CC */ /*--------------------------*/ error = GEN_AcquireCCLock(hwBaseAddress); if (error != DX_OK) return error; /* Go over the VRL list in a loop till a VRL passes verification */ /*---------------------------------------------------------------*/ for (i = 0; i < numOfVrlInList; i++) { /* 1. Verify the VRL RSA signature and public key */ /*------------------------------------------------*/ error = DX_BIV_VRLVerification(NVM_ReadHASHPubKey, /* Get OTP */ flashRead_func, userContext, hwBaseAddress, DX_TRUE, &vrlList[i], DX_NOT_TO_SET_PKA_OFFSET, secondaryNHash, workspace_ptr, workspaceSize); /* In case of error continue to the next VRL in list */ if (error != DX_OK) { DX_PAL_LOG_DEBUG("DX_BIV_VRLVerification returned 0x%X\n", (unsigned int)error); continue; } /* 2. Validate the SW components */ /*-------------------------------*/ /* For each SW component in a loop load (if required) the SW component and verify its HASH */ error = DX_BIV_SWCompValidation(flashRead_func, userContext, hwBaseAddress, &swCompsData, &isSecExist, workspace_ptr, workspaceSize); if (error != DX_OK) { DX_PAL_LOG_DEBUG("DX_BIV_SWCompValidation returned 0x%X\n", (unsigned int)error); continue; } /* If operation succeeded => quit from the loop and return the index of the VRL that passed the verification */ if (error == DX_OK && isSecExist == DX_FALSE) { /* the validated index */ *index_ptr = i; goto RELEASE_AND_RETURN; } /* 5. In case there is a secondary VRL, need to verify it */ /*--------------------------------------------------------*/ if (error == DX_OK && isSecExist == DX_TRUE) { /* Get secondary data (if exist) */ DX_BIV_ParseVrlGetSecData(workspace_ptr, secondaryNHash, swCompsData.hashSizeWords, &secVrlData.VRL_Address); secVrlData.Magic_Number = vrlList[i].Magic_Number; /* 1. Load the VRL from the Flash */ /*--------------------------------*/ error = DX_BIV_VRLVerification(NVM_ReadHASHPubKey, /* Get OTP */ flashRead_func, userContext, hwBaseAddress, DX_FALSE, &secVrlData, DX_NOT_TO_SET_PKA_OFFSET, secondaryNHash, workspace_ptr, workspaceSize); /* In case of failure go to the next VRL in the table */ if (error != DX_OK){ DX_PAL_LOG_DEBUG("DX_BIV_VRLVerification returned 0x%X\n", (unsigned int)error); continue; } /* 2. Validate the SW components */ /*-------------------------------*/ /* For each SW component in a loop load (if required) the SW component and verify its HASH */ error = DX_BIV_SWCompValidation(flashRead_func, userContext, hwBaseAddress, &swCompsData, &isSecExist, workspace_ptr, workspaceSize); if (error != DX_OK) { DX_PAL_LOG_DEBUG("DX_BIV_SWCompValidation returned 0x%X\n", (unsigned int)error); continue; } else { /* If verification succeeded of the secondary VRL return the index of the Primary VRL that was validated */ /* the validated index */ *index_ptr = i; goto RELEASE_AND_RETURN; } }/* End of Secondary VRL verification */ }/* End of VRL table loop */ /* If the loop ended without a validated VRL return error */ error = DX_BOOT_IMG_VERIFIER_NO_VRL_PASSED_VALIDATION; DX_PAL_LOG_DEBUG("no VRL passes validation\n"); RELEASE_AND_RETURN: GEN_ReleaseCCLock(hwBaseAddress); return error; } /* End of DX_BIV_SwImageVerification */
/** * @brief This function is responsible to verification of a VRL. * The verification process verifies the following: * 1. The primary public key as saved in the VRL versus the HASHd public key that is saved in the NVM/OTP * 2. The RSA signature of the VRL * * @param[in] SB_GetOTPHASH_func - Function pointer to user's * get public key HASH function * @param[in] flashRead_func - User's Flash read function used * to read data from the flash to memory location * @param[in] userContext - User's context for the usage of flashRead_func * @param[in] hwBaseAddress - base address for the CC HW engines * @param[in] isPrimaryVRL - an indicator if this is a primary * VRL (TRUE for primary, FALSE for secondary) * @param[in] vrlData - VRL data including storage address, * magic number etc. * @param[out] secondaryNHASH - will contain the secondary * public key HASH * @param[in] workspace_ptr - temporary buffer to load the VRL and SW components to * @param[in] workspaceSize - the temporary buffer size in bytes * * @return DxError_t - On success the value DX_OK is returned, * on failure - a value from BootImagesVerifier_error.h */ DxError_t DX_BIV_VRLVerification(Dx_SB_GetOTPHASH SB_GetOTPHASH_func, DX_SB_FlashRead flashRead_func, void *userContext, DxUint32_t hwBaseAddress, DxUint8_t isPrimaryVRL, SW_Verification_Data_t *vrlData, DxUint32_t pkaOffset, DxUint32_t *secondaryNHASH, DxUint32_t *workspace_ptr, DxUint32_t workspaceSize) { /* error return */ DxError_t error = DX_OK; /* pointers to inside the VRL */ DxUint32_t *VRL_ptr = workspace_ptr; /* public key hash saved in the NVM/OTP */ HASH_Result_t savedPublicKeyHASH; /* temporary buffer */ DxUint32_t VRLBufferSize = workspaceSize; /* SW minimum version */ DxUint32_t savedSwMinVersion = 0; /* secondary VRL address */ VRL_SecAddress_t secVRLAddress; /*------------------ CODE -------------------*/ #ifndef DX_SB_USE_RSA_SW /* Set the PKA offset if it is not set */ if (pkaOffset != DX_NOT_TO_SET_PKA_OFFSET) { DX_PAL_LOG_DEBUG("PKA offset is not set\n"); return DX_BOOT_IMG_VERIFIER_INV_INPUT_PARAM; } #endif /* 1. Get the sw minimum version from the NVM/OTP (if supported) */ /*---------------------------------------------------------------*/ #ifndef DX_OTP_SW_VERSION_NOT_SUPPORTED error = NVM_GetSwVersion(hwBaseAddress, &savedSwMinVersion); if (error != DX_OK) return error; #endif /* 2. Get the public key (N||Np) hash from the NVM/OTP or from the external HASH */ /*-------------------------------------------------------------------------------*/ if (isPrimaryVRL == DX_TRUE) { error = DX_BIV_GetPrimaryKeyHash(SB_GetOTPHASH_func, hwBaseAddress, savedPublicKeyHASH, vrlData->OTP_Key_Index, vrlData->Ext_HASH_Value); if (error != DX_OK){ DX_PAL_LOG_DEBUG("DX_BIV_GetPrimaryKeyHash returned 0x%X\n", (unsigned int)error); return error; } } /* 3. Load the VRL from the Flash */ /*--------------------------------*/ error = DX_BIV_VRLParserLoadVRL(flashRead_func, userContext, /* Flash read function & parameter */ vrlData->VRL_Address, /* VRL address inside the array */ vrlData->Magic_Number, /* expected magic number */ VRL_ptr, /* start of the workspace buffer */ &VRLBufferSize /* Size of the workspace buffer */ ); if (error != DX_OK){ DX_PAL_LOG_DEBUG("DX_BIV_VRLParserLoadVRL returned 0x%X\n", (unsigned int)error); return error; } /* 4. Parse the VRL, verify the RSA signature */ /*--------------------------------------------*/ error = DX_BIV_VRLParser(isPrimaryVRL, /* indicating if this is Primary VRL */ hwBaseAddress, /* base address for CC HW */ savedPublicKeyHASH, /* PubHash*/ savedSwMinVersion, /* Sw Min Version */ VRL_ptr, /* a pointer to the VRL */ &secVRLAddress, /* Secondary VRL address, 0 means there is no second VRL */ secondaryNHASH); /* N buffer, secondary N will be copied to it if secondary VRL exist*/ if (error != DX_OK){ DX_PAL_LOG_DEBUG("DX_BIV_VRLParser returned 0x%X\n", (unsigned int)error); } return error; }/*End of DX_BIV_VRLVerification */
/** * @brief This function is responsible to return the load * address and the sw image size according to given index * * @param[in] vrlPtr - pointer to the vrl * @param[in] swCompIndex - index of the imgae * @param[out] swCompInfo - load address and size * * @return DxError_t - On success the value DX_OK is returned, * on failure - a value from BootImagesVerifier_error.h */ DxError_t DX_BIV_GetSWImageInfo(DxUint32_t *vrlPtr, DxUint32_t swCompIndex, VRL_Internal_SW_Comp_Data_t *swCompInfo) { /* error */ DxError_t error = DX_OK; /* sw comp data */ VRL_Parser_CompsData_t swCompsData; /* pointer to required additional data */ VRL_ParamRecordInfo_t *recInfo_ptr; /* temp vrl header */ VRL_Header_t *vrlHeaderPtr; /* number of SW components */ DxUint32_t numOfComps = 0; /* temp pointer to VRL */ DxUint32_t *tempVRLPtr = vrlPtr; /*------------------ CODE -------------------*/ /* Check inputs */ if (vrlPtr == DX_NULL){ DX_PAL_LOG_DEBUG("VRL ptr is NULL\n"); return DX_BOOT_IMG_VERIFIER_INV_INPUT_PARAM; } /* In case there is additional data - need to skip it */ #ifdef DX_SB_ADDITIONAL_DATA_SUPPORTED /* set the temporary address to after the additional data header */ tempVRLPtr = tempVRLPtr + ADDITIONAL_DATA_SIZE_IN_BYTES/sizeof(DxUint32_t); #endif /* parse the VRL to point to the storage addresses */ /*-------------------------------------------------*/ vrlHeaderPtr = (VRL_Header_t*)tempVRLPtr; /* Calculate the VRL size according to offset to signature + sec address + num of comps * (comps params) */ /*-------------------------------------------------------------------------------------------------------*/ /* Get the number of sw comnponents from the header vrlSize field */ numOfComps = (vrlHeaderPtr->vrlSize & VRL_LEN_NUM_OF_COMPS_BIT_MASK ) >> VRL_LEN_NUM_OF_COMPS_BIT_LOCATION; if (swCompIndex > (numOfComps-1)) { DX_PAL_LOG_DEBUG("Invalid index\n"); return DX_BOOT_IMG_VERIFIER_INV_INPUT_PARAM; } /* parse the vrl get the sw comp data */ error = DX_BIV_ParseVrlGetSWComponentData(vrlPtr, &swCompsData, DX_NULL); if (error != DX_OK) { return error; } /* according to the index get the load address */ swCompInfo->loadAddress = *(swCompsData.swHASHData_ptr + swCompIndex*(swCompsData.hashSizeWords + 1) + swCompsData.hashSizeWords); /* Point to record additional info */ recInfo_ptr = (VRL_ParamRecordInfo_t*)(swCompsData.swAdditionalData_ptr + swCompIndex*(sizeof(VRL_ParamRecordInfo_t)/sizeof(DxUint32_t))); /* return the size */ swCompInfo->swCompSizeBytes = recInfo_ptr->Len * sizeof(DxUint32_t); return DX_OK; }/* End of DX_BIV_SetSramPkaAddr */