/* * Copyright (C) 2017-2020 Alibaba Group Holding Limited */ /* eip76_sp80090.c * * Module implements the SP 800-90 Post Processor interface */ /*---------------------------------------------------------------------------- * This module implements (provides) the following interface(s): */ // EIP-76 External Post Processor Interface #include "eip76_pp.h" // EIP-76 Internal Post Processor Interface #include "eip76_internal_pp.h" // EIP76_Internal_PostProcessor_* /*---------------------------------------------------------------------------- * This module uses (requires) the following interface(s): */ // Default configuration #include "c_eip76.h" // Driver Framework Basic Definitions API #include "basic_defs.h" // uint32_t // Driver Framework Device API #include "device_types.h" // Device_Handle_t // EIP-76 Driver Library Types API #include "eip76_types.h" // EIP76_* types // EIP-76 Driver Library Internal interfaces #include "eip76_level0.h" // Level 0 macros #include "eip76_internal.h" // Internal macros #include "eip76_fsm.h" // State machine /*---------------------------------------------------------------------------- * Definitions and macros */ /*---------------------------------------------------------------------------- * EIP76Lib_PS_AI_Write * */ static EIP76_Status_t EIP76Lib_PS_AI_Write( const Device_Handle_t Device, const uint32_t * PS_AI_Data_p, const unsigned int PS_AI_WordCount, EIP76_EventStatus_t * const Events_p) { uint32_t RegVal; RegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (RegVal & EIP76_EVENTS_MASK); // Ensure test ready state before writing AI for re-seed if(((RegVal & EIP76_STATUS_TEST_READY) == 0 ) && ((RegVal & EIP76_STATUS_RESEED_AI) == 0 )) return EIP76_ILLEGAL_IN_STATE; EIP76_Internal_PostProcessor_PS_AI_Write(Device, PS_AI_Data_p, PS_AI_WordCount); // CDS point: check if PS / AI word 11 is written, // if not then write a dummy word for CDS with device if( PS_AI_WordCount < EIP76_MAX_PS_AI_WORD_COUNT ) EIP76_Write32(Device, EIP76_REG_PS_AI_11, 0); return EIP76_NO_ERROR; } /*---------------------------------------------------------------------------- * EIP76_Internal_PostProcessor_PS_AI_Write * */ void EIP76_Internal_PostProcessor_PS_AI_Write( const Device_Handle_t Device, const uint32_t * PS_AI_Data_p, const unsigned int PS_AI_WordCount) { unsigned int i; for(i = 0; i < PS_AI_WordCount; i++) EIP76_Write32(Device, (unsigned int)(EIP76_REG_PS_AI_0 + i * sizeof(uint32_t)), PS_AI_Data_p[i]); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_BlockCount_Get * * Counter for 128 bits blocks generated by the post-processor, forced to zero * when the post-processor is disabled, cleared to zero when an internal * re-seed operation has finished. This register can be used * to determine when to re-seed the post-processor. * * In the case of SP 800-90 post-processing (EIP-76d), three 128-bit blocks * are post-processed from 384 bits of entropy resulting from a ‘Generate’ * operation. Therefore, this counter runs 3 times as fast and does not count * the number of ‘Generate’ operations performed then. */ EIP76_Status_t EIP76_PostProcessor_BlockCount_Get( EIP76_IOArea_t * const IOArea_p, uint32_t * const BlockCount_p) { #if (EIP76_POST_PROCESSOR_TYPE == EIP76_POST_PROCESSOR_NONE) IDENTIFIER_NOT_USED(IOArea_p); *BlockCount_p = 0; #else Device_Handle_t Device; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(BlockCount_p); Device = TrueIOArea_p->Device; *BlockCount_p = EIP76_BLOCKCNT_RD_BLOCKCOUNT(Device); #endif return EIP76_NO_ERROR; } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_IsBusy * */ EIP76_Status_t EIP76_PostProcessor_IsBusy( EIP76_IOArea_t * const IOArea_p, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; uint32_t StatusRegVal, ControlRegVal; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(Events_p); // No events detected yet *Events_p = 0; Device = TrueIOArea_p->Device; StatusRegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (StatusRegVal & EIP76_EVENTS_MASK); // Check if re-seed is ready ControlRegVal = EIP76_CONTROL_RD(Device); // Check if re-seed is still ongoing if ( (ControlRegVal & EIP76_CONTROL_ENABLE_RESEED) == 0 ) { // Re-seed operation is ready, transit to a new state return EIP76_State_Set((volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_RANDOM_GENERATING); } else { // Re-seed is not ready, // remain in EIP76_STATE_SP80090_RESEED_START state return EIP76_BUSY_RETRY_LATER; } } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_Reseed_Start * */ EIP76_Status_t EIP76_PostProcessor_Reseed_Start( EIP76_IOArea_t * const IOArea_p, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; uint32_t RegVal; EIP76_Status_t rv; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); #if (EIP76_POST_PROCESSOR_TYPE == EIP76_POST_PROCESSOR_BC_DF) uint32_t Mask = EIP76_STATUS_RESEED_AI; #else uint32_t Mask = EIP76_STATUS_TEST_READY; #endif EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(Events_p); // No events detected yet *Events_p = 0; // Transit to a new state rv = EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State, EIP76_STATE_SP80090_RESEED_START); if (rv != EIP76_NO_ERROR) { return rv; } Device = TrueIOArea_p->Device; RegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (RegVal & EIP76_EVENTS_MASK); /* 7 step */ printf("===%s, %d\n", __FUNCTION__, __LINE__); EIP76_Write32(NULL, EIP76_REG_CONTROL, 0x10000); printf("===%s, %d\n", __FUNCTION__, __LINE__); // Start Post Processor re-seed EIP76_CONTROL_WR(Device, EIP76_CONTROL_ENABLE_RESEED); // Check if re-seed is ready RegVal = EIP76_STATUS_RD(Device); while ( (RegVal & Mask) == 0 ) { RegVal = EIP76_STATUS_RD(Device); } // if ( (RegVal & Mask) == 0 ) // { // // Re-seed is not ready // return EIP76_BUSY_RETRY_LATER; // } // Transit to a new state return EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State, EIP76_STATE_SP80090_RESEED_READY); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_Reseed_Write * */ EIP76_Status_t EIP76_PostProcessor_Reseed_Write( EIP76_IOArea_t * const IOArea_p, const uint32_t * PS_AI_Data_p, const unsigned int PS_AI_WordCount, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; EIP76_Status_t rv; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(PS_AI_Data_p); EIP76_CHECK_INT_INRANGE(PS_AI_WordCount, EIP76_MIN_PS_AI_WORD_COUNT, EIP76_MAX_PS_AI_WORD_COUNT); EIP76_CHECK_POINTER(Events_p); // No events detected yet *Events_p = 0; Device = TrueIOArea_p->Device; rv = EIP76Lib_PS_AI_Write(Device, PS_AI_Data_p, PS_AI_WordCount, Events_p); if( rv != EIP76_NO_ERROR ) return rv; /* 11 step */ printf("===%s, %d\n", __FUNCTION__, __LINE__); while ((EIP76_Read32(NULL, EIP76_REG_CONTROL) & 0x00008000) != 0) ; printf("===%s, %d\n", __FUNCTION__, __LINE__); // Transit to a new state rv = EIP76_State_Set((volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_SP80090_RESEED_WRITING); if( rv != EIP76_NO_ERROR ) return rv; //return EIP76_BUSY_RETRY_LATER; /* NOTE debug */ return EIP76_NO_ERROR; } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_NIST_Write * */ EIP76_Status_t EIP76_PostProcessor_NIST_Write( EIP76_IOArea_t * const IOArea_p, const uint32_t * PS_AI_Data_p, const unsigned int PS_AI_WordCount, const unsigned int VectorType, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; EIP76_Status_t rv; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(PS_AI_Data_p); EIP76_CHECK_INT_INRANGE(PS_AI_WordCount, EIP76_MIN_PS_AI_WORD_COUNT, EIP76_MAX_PS_AI_WORD_COUNT); EIP76_CHECK_POINTER(Events_p); // No events detected yet *Events_p = 0; Device = TrueIOArea_p->Device; // Read and discard the output data so that // EIP76_PostProcessor_Result_Read can read the right test result if(VectorType != 0) { EIP76_OUTPUT_0_RD(Device); EIP76_OUTPUT_1_RD(Device); EIP76_OUTPUT_2_RD(Device); EIP76_OUTPUT_3_RD(Device); } rv = EIP76Lib_PS_AI_Write(Device, PS_AI_Data_p, PS_AI_WordCount, Events_p); if( rv != EIP76_NO_ERROR ) return rv; return EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_PROCESSING); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_PS_AI_Write * */ EIP76_Status_t EIP76_PostProcessor_PS_AI_Write( EIP76_IOArea_t * const IOArea_p, const uint32_t * PS_AI_Data_p, const unsigned int PS_AI_WordCount, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; uint32_t RegVal; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(PS_AI_Data_p); EIP76_CHECK_INT_INRANGE(PS_AI_WordCount, EIP76_MIN_PS_AI_WORD_COUNT, EIP76_MAX_PS_AI_WORD_COUNT); EIP76_CHECK_POINTER(Events_p); Device = TrueIOArea_p->Device; RegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (RegVal & EIP76_EVENTS_MASK); EIP76_Internal_PostProcessor_PS_AI_Write(Device, PS_AI_Data_p, PS_AI_WordCount); // Check if PS / AI word 11 is written. // If not then write a dummy word for CDS with device if( PS_AI_WordCount < EIP76_MAX_PS_AI_WORD_COUNT ) EIP76_Write32(Device, EIP76_REG_PS_AI_11, 0); return EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_RANDOM_GENERATING); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_Key_Write * */ EIP76_Status_t EIP76_PostProcessor_Key_Write( EIP76_IOArea_t * const IOArea_p, const uint32_t * Key_Data_p) { Device_Handle_t Device; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(Key_Data_p); Device = TrueIOArea_p->Device; // Write 8 32-bit words as key-data, specific for SP 800-90 PP EIP76_KEY_WR(Device, Key_Data_p, 8); return EIP76_NO_ERROR; } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_Input_Write * * SP 800-90 AES-256 Core known-answer test only! */ EIP76_Status_t EIP76_PostProcessor_Input_Write( EIP76_IOArea_t * const IOArea_p, const uint32_t * Input_Data_p, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; uint32_t StatusRegVal; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(Events_p); EIP76_CHECK_POINTER(Input_Data_p); // No events detected yet *Events_p = 0; Device = TrueIOArea_p->Device; StatusRegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (StatusRegVal & EIP76_EVENTS_MASK); // Write the input data EIP76_INPUT_0_WR(Device, Input_Data_p[0]); EIP76_INPUT_1_WR(Device, Input_Data_p[1]); EIP76_INPUT_2_WR(Device, Input_Data_p[2]); // CDS point: device takes over here EIP76_INPUT_3_WR(Device, Input_Data_p[3]); // Input data written, transit to a new state return EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_PROCESSING); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_Result_Read * * This function can also be used for the SP 800-90 Post Processor to read * 1) result of the AES-256 Core known-answer test * 2) result of the NIST known-answer test on the complete Post Processor */ EIP76_Status_t EIP76_PostProcessor_Result_Read( EIP76_IOArea_t * const IOArea_p, uint32_t * Output_Data_p, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; uint32_t RegVal; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(Events_p); EIP76_CHECK_POINTER(Output_Data_p); // No events detected yet *Events_p = 0; Device = TrueIOArea_p->Device; RegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (RegVal & EIP76_EVENTS_MASK); // Ensure test ready state before reading out test result if( (RegVal & EIP76_STATUS_TEST_READY) == 0 ) return EIP76_ILLEGAL_IN_STATE; Output_Data_p[0] = EIP76_OUTPUT_0_RD(Device); Output_Data_p[1] = EIP76_OUTPUT_1_RD(Device); Output_Data_p[2] = EIP76_OUTPUT_2_RD(Device); Output_Data_p[3] = EIP76_OUTPUT_3_RD(Device); // Leave Test Mode RegVal = EIP76_TEST_RD(Device); // Clear all existing tests that could have been started RegVal &= (~( EIP76_TEST_POST_PROC | EIP76_TEST_SP_800_90 | EIP76_TEST_KNOWN_NOISE)); EIP76_TEST_WR(Device, RegVal); // Restore TRNG_CONTROL register (internal TRNG HW state) stored // when the test was started EIP76_CONTROL_WR(Device, TrueIOArea_p->SavedControl); // Input data written, transit to a new state return EIP76_State_Set((volatile EIP76_State_t*)&TrueIOArea_p->State, EIP76_STATE_RANDOM_GENERATING); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_IsReady * */ EIP76_Status_t EIP76_PostProcessor_IsReady( EIP76_IOArea_t * const IOArea_p, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; uint32_t StatusRegVal; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(Events_p); // No events detected yet *Events_p = 0; Device = TrueIOArea_p->Device; StatusRegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (StatusRegVal & EIP76_EVENTS_MASK); #if (EIP76_POST_PROCESSOR_TYPE == EIP76_POST_PROCESSOR_BC_DF) if ((StatusRegVal & EIP76_STATUS_RESEED_AI) != 0 ) { // Goto next state. return EIP76_State_Set((volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_SP80090_RESEED_READY); } #else if ((StatusRegVal & EIP76_STATUS_TEST_READY) != 0 ) { // Goto next state. return EIP76_State_Set((volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_RANDOM_GENERATING); } #endif else { // reseed_ai/test bit is not active return EIP76_BUSY_RETRY_LATER; } } #if (EIP76_POST_PROCESSOR_TYPE == EIP76_POST_PROCESSOR_BC_DF) /*---------------------------------------------------------------------------- * EIP76_PostProcessor_BCDF_PS_AI_Write * */ EIP76_Status_t EIP76_PostProcessor_BCDF_PS_AI_Write( EIP76_IOArea_t * const IOArea_p, const uint32_t * PS_AI_Data_p, const unsigned int PS_AI_WordCount, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; uint32_t RegVal; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(PS_AI_Data_p); EIP76_CHECK_INT_INRANGE(PS_AI_WordCount, EIP76_MAX_PS_AI_WORD_COUNT, EIP76_MAX_PS_AI_WORD_COUNT); EIP76_CHECK_POINTER(Events_p); Device = TrueIOArea_p->Device; RegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (RegVal & EIP76_EVENTS_MASK); EIP76_Internal_PostProcessor_PS_AI_Write(Device, PS_AI_Data_p, PS_AI_WordCount); TrueIOArea_p->Index = 0; return EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_BCDF_RESEEDED); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_BCDF_Noise_Write * */ EIP76_Status_t EIP76_PostProcessor_BCDF_Noise_Write( EIP76_IOArea_t * const IOArea_p, uint32_t * const Noise_Data, const unsigned int Noise_Count) { uint32_t RegValue; Device_Handle_t Device; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); Device = TrueIOArea_p->Device; RegValue = (((Noise_Data[TrueIOArea_p->Index] & 0x7FFFFFFF) << 1) | ((Noise_Data[TrueIOArea_p->Index+1] >> 31) & 0x00000001)); EIP76_MAINSHIFTREG_L_WR(Device, RegValue); RegValue = (((Noise_Data[TrueIOArea_p->Index+1] & 0x7FFFFFFF) << 1) | ((Noise_Data[TrueIOArea_p->Index] >> 31) & 0x00000001)); EIP76_MAINSHIFTREG_H_WR(Device, RegValue); TrueIOArea_p->Index += 2; if (TrueIOArea_p->Index >= Noise_Count) TrueIOArea_p->Index = 0; // Reset index for next loop // One noise block is written, transit to a new state return EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_BCDF_NOISE); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_BCDF_Status_Get * */ EIP76_Status_t EIP76_PostProcessor_BCDF_Status_Get( EIP76_IOArea_t * const IOArea_p, EIP76_EventStatus_t * const Events_p) { EIP76_Status_t rv; Device_Handle_t Device; uint32_t StatusRegVal; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(Events_p); Device = TrueIOArea_p->Device; StatusRegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (StatusRegVal & EIP76_EVENTS_MASK); if (StatusRegVal & EIP76_STATUS_TEST_READY) { // Raw noise block is processed, check if the last one if (TrueIOArea_p->Index) { EIP76_Status_t rv = EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_BCDF_RESEEDED); if( rv != EIP76_NO_ERROR ) return rv; // Not all noise blocks are processed yet, more input data needed return EIP76_PROCESSING; } else // All noise blocks are processed return EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_BCDF_READY); } // status is not ready, stay in current state rv = EIP76_State_Set((volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_BCDF_NOISE); if (rv != EIP76_NO_ERROR) return rv; return EIP76_BUSY_RETRY_LATER; } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_BCDF_Generate_Start * */ EIP76_Status_t EIP76_PostProcessor_BCDF_Generate_Start( EIP76_IOArea_t * const IOArea_p, const unsigned int WordCount, EIP76_EventStatus_t * const Events_p) { Device_Handle_t Device; uint32_t ControlValue, StatusValue, AvailBlkCnt, ReqBlkCnt, WriteValue; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); Device = TrueIOArea_p->Device; ControlValue = EIP76_CONTROL_RD(Device); // First check if number of data_bloacks is zero, else return if ((ControlValue >> 20) & MASK_12_BITS) return EIP76_BUSY_RETRY_LATER; // Calculate requested 128-bit random data blocks ReqBlkCnt = (WordCount + 3) / 4; // Round up StatusValue = EIP76_STATUS_RD(Device); // Store event status *Events_p = (StatusValue & EIP76_EVENTS_MASK); // Get the number of available 128-bit random data blocks AvailBlkCnt = (StatusValue & MASK_1_BIT) + // in output registers ((StatusValue >> 16) & MASK_8_BITS); // in buffer RAM // Check if requested number of bytes is already available if(AvailBlkCnt < ReqBlkCnt) { EIP76_CHECK_INT_ATMOST(ReqBlkCnt - AvailBlkCnt, EIP76_REQUEST_DATA_MAX_BLK_COUNT); // Only data_blocks field is updated in register WriteValue = EIP76_REQUEST_DATA | (((ReqBlkCnt - AvailBlkCnt) & MASK_12_BITS) << 20); EIP76_CONTROL_WR(Device, WriteValue); } // Transit to a new state return EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_BCDF_PROCESSING); } /*---------------------------------------------------------------------------- * EIP76_PostProcessor_BCDF_Result_Read * */ EIP76_Status_t EIP76_PostProcessor_BCDF_Result_Read( EIP76_IOArea_t * const IOArea_p, EIP76_EventStatus_t * const Events_p, uint32_t * const Data_p, const unsigned int Data_WordCount) { EIP76_Status_t rv; Device_Handle_t Device; uint32_t RegVal; volatile EIP76_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p); EIP76_CHECK_POINTER(IOArea_p); EIP76_CHECK_POINTER(Events_p); EIP76_CHECK_INT_ATMOST(Data_WordCount, (unsigned int)MASK_31_BITS); Device = TrueIOArea_p->Device; RegVal = EIP76_STATUS_RD(Device); // Store event status *Events_p = (RegVal & EIP76_EVENTS_MASK); if (EIP76_STATUS_IS_READY(RegVal)) { Data_p[TrueIOArea_p->Index + 0] = EIP76_OUTPUT_0_RD(Device); Data_p[TrueIOArea_p->Index + 1] = EIP76_OUTPUT_1_RD(Device); Data_p[TrueIOArea_p->Index + 2] = EIP76_OUTPUT_2_RD(Device); Data_p[TrueIOArea_p->Index + 3] = EIP76_OUTPUT_3_RD(Device); TrueIOArea_p->Index += 4; // Clear ready bit when done reading result EIP76_INTACK_WR(Device, CLEAR_READY_BIT); if (TrueIOArea_p->Index >= Data_WordCount) { // Reset back for next loop TrueIOArea_p->Index = 0; // Check if 2nd Generate function must be requested if (TrueIOArea_p->Flag) { // Leave Test Mode RegVal = EIP76_TEST_RD(Device); // Clear all existing tests that could have been started RegVal &= (~(EIP76_TEST_POST_PROC | EIP76_TEST_SP_800_90 | EIP76_TEST_KNOWN_NOISE)); EIP76_TEST_WR(Device, RegVal); // Restore TRNG_CONTROL register (internal TRNG HW state) stored // when the test was started EIP76_CONTROL_WR(Device, TrueIOArea_p->SavedControl); TrueIOArea_p->Flag = false; // Advance the FSM to prepare for the Personalization String // re-write after test rv = EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_RANDOM_GENERATING); if (rv != EIP76_NO_ERROR) return rv; // Now the FSM is ready for EIP76_PostProcessor_IsReady() // and consequent EIP76_PostProcessor_Reseed_Write() calls // to re-write the Personalization String return EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_SP80090_RESEED_START); } else { // Ignore the result of the 1st Generate function and // repeat part of the test for the 2nd Generate function rv = EIP76_State_Set( (volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_KAT_START); if (rv != EIP76_NO_ERROR) return rv; // Request 2nd Generate function TrueIOArea_p->Flag = true; // Request a re-seed EIP76_CONTROL_WR(Device, EIP76_CONTROL_ENABLE_RESEED); return EIP76_PROCESSING; } } } // Requested random data is not ready or // not all requested data blocks are red, stay in current state rv = EIP76_State_Set((volatile EIP76_State_t* const)&TrueIOArea_p->State, EIP76_STATE_KAT_SP80090_BCDF_PROCESSING); if (rv != EIP76_NO_ERROR) return rv; return EIP76_BUSY_RETRY_LATER; } #endif // (EIP76_POST_PROCESSOR_TYPE == EIP76_POST_PROCESSOR_BC_DF) /* end of file eip76_sp80090.c */