mirror of
https://github.com/revyos/th1520-vendor-uboot.git
synced 2026-09-18 05:12:09 +02:00
888 lines
26 KiB
C
888 lines
26 KiB
C
/*
|
||
* 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 */
|
||
|