1608 lines
54 KiB
C
1608 lines
54 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipfreescale_coldfire.c,v $ $Revision: 1.14 $
|
|
* $Source: /home/interpeak/CVSRoot/ipfreescale/src/ipfreescale_coldfire.c,v $
|
|
* $Author: markus $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Markus Carlstedt <markus@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
* IPFREESCALE - Hardware crypto support product - coldfire implementation.
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipfreescale_config.h"
|
|
|
|
#ifdef IPFREESCALE_COLDFIRE
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_err.h>
|
|
#include <ipcom_os.h>
|
|
|
|
#include <iphwcrypto.h>
|
|
|
|
#include "ipfreescale.h"
|
|
#include "ipfreescale_h.h"
|
|
#include "ipfreescale_coldfire.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* Array used for des key parity fix */
|
|
#ifdef IPFREESCALE_COLDFIRE_FIX_DES_PARITY
|
|
IP_CONST Ip_u8 ipfreescale_parity_odd[256] =
|
|
{
|
|
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
|
|
16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
|
|
32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
|
|
49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
|
|
64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
|
|
81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
|
|
97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
|
|
112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
|
|
128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
|
|
145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
|
|
161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
|
|
176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
|
|
193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
|
|
208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
|
|
224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
|
|
241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254
|
|
};
|
|
#endif
|
|
|
|
/* Global data for coldfire implementation */
|
|
IP_GLOBAL Ipfreescale_coldfire_data ipfreescale_coldfire;
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_eu_reset
|
|
*===========================================================================
|
|
* Description: Reset a SEC execution unit.
|
|
* Parameters: eu - execution unit to reset.
|
|
* Returns: 0 = success.
|
|
* -1 = fail.
|
|
*/
|
|
IP_STATIC int
|
|
ipfreescale_coldfire_eu_reset(int eu)
|
|
{
|
|
IP_VOLATILE Ip_u32 *rcr;
|
|
IP_VOLATILE Ip_u32 *sr;
|
|
int maxwait = IPFREESCALE_COLDFIRE_MAXWAIT;
|
|
|
|
switch(eu)
|
|
{
|
|
case IPFREESCALE_COLDFIRE_EU_AFEU:
|
|
rcr = ipfreescale_coldfire.afrcr;
|
|
sr = ipfreescale_coldfire.afsr;
|
|
break;
|
|
case IPFREESCALE_COLDFIRE_EU_DEU:
|
|
rcr = ipfreescale_coldfire.drcr;
|
|
sr = ipfreescale_coldfire.dsr;
|
|
break;
|
|
case IPFREESCALE_COLDFIRE_EU_MDEU:
|
|
rcr = ipfreescale_coldfire.mdrcr;
|
|
sr = ipfreescale_coldfire.mdsr;
|
|
break;
|
|
case IPFREESCALE_COLDFIRE_EU_RNG:
|
|
rcr = ipfreescale_coldfire.rngrcr;
|
|
sr = ipfreescale_coldfire.rngsr;
|
|
break;
|
|
case IPFREESCALE_COLDFIRE_EU_AESU:
|
|
rcr = ipfreescale_coldfire.aesrcr;
|
|
sr = ipfreescale_coldfire.aessr;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
/* Reset the execution unit */
|
|
IP_BIT_SET(*rcr, IPFREESCALE_COLDFIRE_RCR_SR);
|
|
/* Wait for reset sequence to complete */
|
|
while(maxwait-- > 0)
|
|
{
|
|
if(IP_BIT_ISSET(*sr, IPFREESCALE_COLDFIRE_SR_RD))
|
|
return 0;
|
|
}
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_channel_reset
|
|
*===========================================================================
|
|
* Description: Reset a SEC channel.
|
|
* Parameters: ch - channel to reset.
|
|
* Returns: 0 = success.
|
|
* -1 = fail.
|
|
*/
|
|
IP_STATIC int
|
|
ipfreescale_coldfire_channel_reset(int ch)
|
|
{
|
|
int maxwait = IPFREESCALE_COLDFIRE_MAXWAIT;
|
|
|
|
/* Reset the channel */
|
|
IP_BIT_SET(*ipfreescale_coldfire.channel[ch].cccr, IPFREESCALE_COLDFIRE_CCCRn_RST);
|
|
/* Wait for reset sequence to complete */
|
|
while(maxwait-- > 0)
|
|
{
|
|
if(!IP_BIT_ISSET(*ipfreescale_coldfire.channel[ch].cccr, IPFREESCALE_COLDFIRE_CCCRn_RST))
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_channel_init
|
|
*===========================================================================
|
|
* Description: Initialize a SEC channel.
|
|
* Parameters: ch - channel to initialize.
|
|
* Returns: 0 = success.
|
|
* -1 = fail.
|
|
*/
|
|
IP_STATIC int
|
|
ipfreescale_coldfire_channel_init(int ch)
|
|
{
|
|
if(ipfreescale_coldfire_channel_reset(ch) != 0)
|
|
return -1;
|
|
|
|
/* Enable channel done interrupt */
|
|
IP_BIT_SET(*ipfreescale_coldfire.channel[ch].cccr, IPFREESCALE_COLDFIRE_CCCRn_CDIE);
|
|
/* Enable fetch next descriptor */
|
|
IP_BIT_SET(*ipfreescale_coldfire.channel[ch].cccr, IPFREESCALE_COLDFIRE_CCCRn_NE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_channel_launch
|
|
*===========================================================================
|
|
* Description: Launch descriptor to SEC channel.
|
|
* Parameters: ch - channel to launch.
|
|
* dp - pointer to descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_channel_launch(int ch, Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
*ipfreescale_coldfire.channel[ch].fr = (Ip_u32)dp;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_channel_waitforcompletion
|
|
*===========================================================================
|
|
* Description: Wait for SEC channel to complete.
|
|
* Parameters: ch - channel to wait for.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_STATIC int
|
|
ipfreescale_coldfire_channel_waitforcompletion(int ch)
|
|
{
|
|
int maxwait = IPFREESCALE_COLDFIRE_MAXWAIT;
|
|
|
|
while(maxwait-- > 0)
|
|
{
|
|
if(ch == 0)
|
|
{
|
|
if(IP_BIT_ISSET(*ipfreescale_coldfire.sisrh, IPFREESCALE_COLDFIRE_SISRH_CHA0DN))
|
|
{
|
|
IP_BIT_SET(*ipfreescale_coldfire.sicrh, IPFREESCALE_COLDFIRE_SICRH_CHA0DN);
|
|
return 1;
|
|
}
|
|
}
|
|
else if(ch == 1)
|
|
{
|
|
if(IP_BIT_ISSET(*ipfreescale_coldfire.sisrh, IPFREESCALE_COLDFIRE_SISRH_CHA1DN))
|
|
{
|
|
IP_BIT_SET(*ipfreescale_coldfire.sicrh, IPFREESCALE_COLDFIRE_SICRH_CHA1DN);
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IP_PANIC();
|
|
}
|
|
|
|
/* Let other tasks run */
|
|
ipfreescale_coldfire_yield_task();
|
|
}
|
|
|
|
/* Check for channel errors */
|
|
if(IP_BIT_ISSET(*ipfreescale_coldfire.channel[ch].ccpsrl, IPFREESCALE_COLDFIRE_CCPSRLn_EUERR
|
|
| IPFREESCALE_COLDFIRE_CCPSRLn_SERR
|
|
| IPFREESCALE_COLDFIRE_CCPSRLn_DERR
|
|
| IPFREESCALE_COLDFIRE_CCPSRLn_PERR
|
|
| IPFREESCALE_COLDFIRE_CCPSRLn_TEA))
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
/* Timeout */
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_reset
|
|
*===========================================================================
|
|
* Description: Reset SEC.
|
|
* Parameters: none.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC int
|
|
ipfreescale_coldfire_reset(void)
|
|
{
|
|
int maxwait = IPFREESCALE_COLDFIRE_MAXWAIT;
|
|
|
|
/* Reset the Coldfire SEC */
|
|
IP_BIT_SET(*ipfreescale_coldfire.mcr, IPFREESCALE_COLDFIRE_SMCR_SWR);
|
|
/* Wait for reset sequence to complete */
|
|
while(maxwait-- > 0)
|
|
{
|
|
if(!IP_BIT_ISSET(*ipfreescale_coldfire.mcr, IPFREESCALE_COLDFIRE_SMCR_SWR))
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_regs
|
|
*===========================================================================
|
|
* Description: Populate SEC register structure.
|
|
* Parameters: none.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_regs(void)
|
|
{
|
|
int i;
|
|
|
|
/* Registers */
|
|
ipfreescale_coldfire.jtagid = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_MCF_JTAGID_OFFSET);
|
|
ipfreescale_coldfire.mcr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_SMCR_OFFSET);
|
|
ipfreescale_coldfire.simrh = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_SIMRH_OFFSET);
|
|
ipfreescale_coldfire.simrl = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_SIMRL_OFFSET);
|
|
ipfreescale_coldfire.sisrh = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_SISRH_OFFSET);
|
|
ipfreescale_coldfire.sisrl = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_SISRL_OFFSET);
|
|
ipfreescale_coldfire.sicrh = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_SICRH_OFFSET);
|
|
ipfreescale_coldfire.sicrl = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_SICRL_OFFSET);
|
|
ipfreescale_coldfire.afrcr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_AFRCR_OFFSET);
|
|
ipfreescale_coldfire.afsr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_AFSR_OFFSET);
|
|
ipfreescale_coldfire.drcr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_DRCR_OFFSET);
|
|
ipfreescale_coldfire.dsr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_DSR_OFFSET);
|
|
ipfreescale_coldfire.mdrcr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_MDRCR_OFFSET);
|
|
ipfreescale_coldfire.mdsr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_MDSR_OFFSET);
|
|
ipfreescale_coldfire.rngrcr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_RNGRCR_OFFSET);
|
|
ipfreescale_coldfire.rngsr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_RNGSR_OFFSET);
|
|
ipfreescale_coldfire.aesrcr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_AESRCR_OFFSET);
|
|
ipfreescale_coldfire.aessr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_AESSR_OFFSET);
|
|
|
|
for(i=0; i<IPFREESCALE_COLDFIRE_NUM_CHANNELS; i++)
|
|
{
|
|
ipfreescale_coldfire.channel[i].cccr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_CCCR_OFFSET + i * IPFREESCALE_COLDFIRE_CHANNEL_OFFSET);
|
|
ipfreescale_coldfire.channel[i].ccpsrh = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_CCPSRH_OFFSET + i * IPFREESCALE_COLDFIRE_CHANNEL_OFFSET);
|
|
ipfreescale_coldfire.channel[i].ccpsrl = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_CCPSRL_OFFSET + i * IPFREESCALE_COLDFIRE_CHANNEL_OFFSET);
|
|
ipfreescale_coldfire.channel[i].fr = (Ip_u32 *)((Ip_u32)IPFREESCALE_COLDFIRE_MBAR + (Ip_u32)IPFREESCALE_COLDFIRE_FR_OFFSET + i * IPFREESCALE_COLDFIRE_CHANNEL_OFFSET);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_channel_error
|
|
*===========================================================================
|
|
* Description: Handle SEC channel error.
|
|
* Parameters: status - error status.
|
|
* ch - channel that caused the error.
|
|
* peu - primary execution unit.
|
|
* seu - secondary execution unit.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_channel_error(int status, int ch, int peu, int seu)
|
|
{
|
|
if(status == 0)
|
|
{
|
|
/* Timeout */
|
|
IPFREESCALE_STATS(ch, e_tmo++);
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Channel %d timed out", ch);
|
|
}
|
|
else
|
|
{
|
|
/* Channel error */
|
|
if(IP_BIT_ISSET(*ipfreescale_coldfire.channel[ch].ccpsrl, IPFREESCALE_COLDFIRE_CCPSRLn_EUERR))
|
|
{
|
|
IPFREESCALE_STATS(ch, e_euerr++);
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Channel %d caused euerr", ch);
|
|
/* Reset the assigned execution units */
|
|
if(ipfreescale_coldfire_eu_reset(peu) != 0)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Failed to reset eu %d", peu);
|
|
}
|
|
if(ipfreescale_coldfire_eu_reset(seu) != 0)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Failed to reset eu %d", seu);
|
|
}
|
|
}
|
|
|
|
if(IP_BIT_ISSET(*ipfreescale_coldfire.channel[ch].ccpsrl, IPFREESCALE_COLDFIRE_CCPSRLn_SERR))
|
|
{
|
|
IPFREESCALE_STATS(ch, e_serr++);
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Channel %d caused serr", ch);
|
|
|
|
}
|
|
|
|
if(IP_BIT_ISSET(*ipfreescale_coldfire.channel[ch].ccpsrl, IPFREESCALE_COLDFIRE_CCPSRLn_DERR))
|
|
{
|
|
IPFREESCALE_STATS(ch, e_derr++);
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Channel %d caused derr", ch);
|
|
}
|
|
|
|
if(IP_BIT_ISSET(*ipfreescale_coldfire.channel[ch].ccpsrl, IPFREESCALE_COLDFIRE_CCPSRLn_PERR))
|
|
{
|
|
IPFREESCALE_STATS(ch, e_perr++);
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Channel %d caused perr", ch);
|
|
}
|
|
|
|
if(IP_BIT_ISSET(*ipfreescale_coldfire.channel[ch].ccpsrl, IPFREESCALE_COLDFIRE_CCPSRLn_TEA))
|
|
{
|
|
IPFREESCALE_STATS(ch, e_tea++);
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Channel %d caused tea", ch);
|
|
}
|
|
}
|
|
|
|
/* Re-initialize the channel */
|
|
if(ipfreescale_coldfire_channel_init(ch) != 0)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_channel_error() :: Failed to initialize channel %d", ch);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_descriptor_create
|
|
*===========================================================================
|
|
* Description: Create a SEC descriptor.
|
|
* Parameters: peu - primary execution unit.
|
|
* seu - secondary execution unit.
|
|
* dp - pointer to SEC descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_descr_create(int peu, int pmode, int type, Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
dp->hdr = peu<<28 | pmode<<20 | type<<4;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_descr_load_rng
|
|
*===========================================================================
|
|
* Description: Load random number generation descriptor.
|
|
* Parameters: data - pointer to random data.
|
|
* length - length of random data.
|
|
* dp - pointer to SEC descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_descr_load_rng(Ip_u8 *data,
|
|
Ip_u32 length,
|
|
Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
dp->len_1 = 0;
|
|
dp->ptr_1 = IP_NULL;
|
|
dp->len_2 = 0;
|
|
dp->ptr_2 = IP_NULL;
|
|
dp->len_3 = 0;
|
|
dp->ptr_3 = IP_NULL;
|
|
dp->len_4 = 0;
|
|
dp->ptr_4 = IP_NULL;
|
|
dp->len_5 = length - length%4; /* Must be multiple of 4 */
|
|
dp->ptr_5 = data;
|
|
dp->len_6 = 0;
|
|
dp->ptr_6 = IP_NULL;
|
|
dp->len_7 = 0;
|
|
dp->ptr_7 = IP_NULL;
|
|
dp->next = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_descr_load_mdeu
|
|
*===========================================================================
|
|
* Description: Load message digest descriptor.
|
|
* Parameters: data - pointer to data to hash.
|
|
* length - length of data to hash.
|
|
* digest - pointer to digest.
|
|
* digestlen - length of digest.
|
|
* dp - pointer to SEC descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_descr_load_mdeu(IP_CONST Ip_u8 *data,
|
|
Ip_u32 length,
|
|
Ip_u8 *digest,
|
|
Ip_u32 digestlen,
|
|
Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
dp->len_1 = 0;
|
|
dp->ptr_1 = IP_NULL;
|
|
dp->len_2 = 0;
|
|
dp->ptr_2 = IP_NULL;
|
|
dp->len_3 = 0;
|
|
dp->ptr_3 = IP_NULL;
|
|
dp->len_4 = length;
|
|
dp->ptr_4 = (Ip_u8 *)data;
|
|
dp->len_5 = 0;
|
|
dp->ptr_5 = IP_NULL;
|
|
dp->len_6 = digestlen;
|
|
dp->ptr_6 = digest;
|
|
dp->len_7 = 0;
|
|
dp->ptr_7 = IP_NULL;
|
|
dp->next = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_descr_load_deu_cbc
|
|
*===========================================================================
|
|
* Description: Load DES-CBC descriptor.
|
|
* Parameters: out - pointer to output data
|
|
* in - pointer to input data
|
|
* length - length of data
|
|
* key - pointer to the key.
|
|
* keylen - length of key.
|
|
* iv - pointer to the initialization vector.
|
|
* dp - pointer to SEC descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_descr_load_deu_cbc(Ip_u8 *out, IP_CONST Ip_u8 *in,
|
|
Ip_u32 length,
|
|
Ip_u8 *key,
|
|
int keylen,
|
|
Ip_u8 *iv,
|
|
Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
dp->len_1 = 0;
|
|
dp->ptr_1 = IP_NULL;
|
|
dp->len_2 = IPFREESCALE_DES_IV_SIZE;
|
|
dp->ptr_2 = iv;
|
|
dp->len_3 = keylen;
|
|
dp->ptr_3 = key;
|
|
dp->len_4 = length;
|
|
dp->ptr_4 = (Ip_u8 *)in;
|
|
dp->len_5 = length;
|
|
dp->ptr_5 = out;
|
|
dp->len_6 = IPFREESCALE_DES_IV_SIZE;
|
|
dp->ptr_6 = iv;
|
|
dp->len_7 = 0;
|
|
dp->ptr_7 = IP_NULL;
|
|
dp->next = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_descr_load_deu_ecb
|
|
*===========================================================================
|
|
* Description: Load DES-ECB descriptor.
|
|
* Parameters: out - pointer to output data
|
|
* in - pointer to input data
|
|
* length - length of data
|
|
* key - pointer to the key.
|
|
* keylen - length of key.
|
|
* dp - pointer to SEC descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_descr_load_deu_ecb(Ip_u8 *out, IP_CONST Ip_u8 *in,
|
|
Ip_u32 length,
|
|
Ip_u8 *key,
|
|
int keylen,
|
|
Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
dp->len_1 = 0;
|
|
dp->ptr_1 = IP_NULL;
|
|
dp->len_2 = 0;
|
|
dp->ptr_2 = IP_NULL;
|
|
dp->len_3 = keylen;
|
|
dp->ptr_3 = key;
|
|
dp->len_4 = length;
|
|
dp->ptr_4 = (Ip_u8 *)in;
|
|
dp->len_5 = length;
|
|
dp->ptr_5 = out;
|
|
dp->len_6 = 0;
|
|
dp->ptr_6 = IP_NULL;
|
|
dp->len_7 = 0;
|
|
dp->ptr_7 = IP_NULL;
|
|
dp->next = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_descr_load_aesu_cbc
|
|
*===========================================================================
|
|
* Description: Load AES-CBC descriptor.
|
|
* Parameters: out - pointer to output data
|
|
* in - pointer to input data
|
|
* length - length of data
|
|
* key - pointer to the key.
|
|
* keylen - length of key.
|
|
* iv - pointer to the initialization vector.
|
|
* dp - pointer to SEC descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_descr_load_aesu_cbc(Ip_u8 *out, IP_CONST Ip_u8 *in,
|
|
Ip_u32 length,
|
|
Ip_u8 *key,
|
|
Ip_u32 keylen,
|
|
Ip_u8 *iv,
|
|
Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
dp->len_1 = 0;
|
|
dp->ptr_1 = IP_NULL;
|
|
dp->len_2 = IPFREESCALE_AES_IV_SIZE;
|
|
dp->ptr_2 = iv;
|
|
dp->len_3 = keylen;
|
|
dp->ptr_3 = key;
|
|
dp->len_4 = length;
|
|
dp->ptr_4 = (Ip_u8 *)in;
|
|
dp->len_5 = length;
|
|
dp->ptr_5 = out;
|
|
dp->len_6 = IPFREESCALE_AES_IV_SIZE;
|
|
dp->ptr_6 = iv;
|
|
dp->len_7 = 0;
|
|
dp->ptr_7 = IP_NULL;
|
|
dp->next = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_descr_load_aesu_ecb
|
|
*===========================================================================
|
|
* Description: Load AES-ECB descriptor.
|
|
* Parameters: out - pointer to output data
|
|
* in - pointer to input data
|
|
* length - length of data
|
|
* key - pointer to the key.
|
|
* keylen - length of key.
|
|
* dp - pointer to SEC descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_descr_load_aesu_ecb(Ip_u8 *out, IP_CONST Ip_u8 *in,
|
|
Ip_u32 length,
|
|
Ip_u8 *key,
|
|
Ip_u32 keylen,
|
|
Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
dp->len_1 = 0;
|
|
dp->ptr_1 = IP_NULL;
|
|
dp->len_2 = 0;
|
|
dp->ptr_2 = IP_NULL;
|
|
dp->len_3 = keylen;
|
|
dp->ptr_3 = key;
|
|
dp->len_4 = length;
|
|
dp->ptr_4 = (Ip_u8 *)in;
|
|
dp->len_5 = length;
|
|
dp->ptr_5 = out;
|
|
dp->len_6 = 0;
|
|
dp->ptr_6 = IP_NULL;
|
|
dp->len_7 = 0;
|
|
dp->ptr_7 = IP_NULL;
|
|
dp->next = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_descr_load_afeu
|
|
*===========================================================================
|
|
* Description: Load RC4 descriptor.
|
|
* Parameters: out - pointer to output data
|
|
* in - pointer to input data
|
|
* length - length of data
|
|
* key - pointer to the key.
|
|
* keylen - length of key.
|
|
* ctxi - pointer to the input context.
|
|
* ctxo - pointer to the output context.
|
|
* dp - pointer to SEC descriptor.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_STATIC void
|
|
ipfreescale_coldfire_descr_load_afeu(Ip_u8 *out, IP_CONST Ip_u8 *in,
|
|
Ip_u32 length,
|
|
Ip_u8 *key,
|
|
Ip_u32 keylen,
|
|
Ip_u8 *ctxi,
|
|
Ip_u8 *ctxo,
|
|
Ipfreescale_coldfire_descriptor *dp)
|
|
{
|
|
dp->len_1 = 0;
|
|
dp->ptr_1 = IP_NULL;
|
|
if(key == IP_NULL)
|
|
{
|
|
dp->len_2 = IPFREESCALE_RC4_CTX_SIZE;
|
|
dp->ptr_2 = ctxi;
|
|
dp->len_3 = 0;
|
|
dp->ptr_3 = IP_NULL;
|
|
}
|
|
else
|
|
{
|
|
dp->len_2 = 0;
|
|
dp->ptr_2 = IP_NULL;
|
|
dp->len_3 = keylen;
|
|
dp->ptr_3 = key;
|
|
}
|
|
dp->len_4 = length;
|
|
dp->ptr_4 = (Ip_u8 *)in;
|
|
dp->len_5 = length;
|
|
dp->ptr_5 = out;
|
|
if(ctxo != IP_NULL)
|
|
{
|
|
dp->len_6 = IPFREESCALE_RC4_CTX_SIZE;
|
|
dp->ptr_6 = ctxo;
|
|
}
|
|
else
|
|
{
|
|
dp->len_6 = 0;
|
|
dp->ptr_6 = IP_NULL;
|
|
}
|
|
dp->len_7 = 0;
|
|
dp->ptr_7 = IP_NULL;
|
|
dp->next = IP_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPFREESCALE_USE_STATISTICS
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_print_stats
|
|
*===========================================================================
|
|
* Description: Print SEC statistics.
|
|
* Parameters: where - output destination ("syslog" or "stdout")
|
|
* Returns: nothing.
|
|
*/
|
|
IP_GLOBAL void
|
|
ipfreescale_coldfire_print_stats(char *where)
|
|
{
|
|
int i;
|
|
char *buf;
|
|
|
|
buf = ipcom_malloc(512);
|
|
if(buf == IP_NULL)
|
|
goto done;
|
|
|
|
for(i=0; i<IPFREESCALE_COLDFIRE_NUM_CHANNELS; i++)
|
|
{
|
|
ipcom_sprintf(buf, "Channel %d:"IP_LF
|
|
" Usage:"IP_LF
|
|
" mdeu: %d"IP_LF
|
|
" deu: %d"IP_LF
|
|
" aesu: %d"IP_LF
|
|
" afeu: %d"IP_LF
|
|
" rng: %d"IP_LF
|
|
" Errors:"IP_LF
|
|
" tmo: %d"IP_LF
|
|
" euerr: %d"IP_LF
|
|
" serr: %d"IP_LF
|
|
" derr: %d"IP_LF
|
|
" perr: %d"IP_LF
|
|
" tea: %d"IP_LF,
|
|
i,
|
|
IPFREESCALE_STATS(i, u_mdeu),
|
|
IPFREESCALE_STATS(i, u_deu),
|
|
IPFREESCALE_STATS(i, u_aesu),
|
|
IPFREESCALE_STATS(i, u_afeu),
|
|
IPFREESCALE_STATS(i, u_rng),
|
|
IPFREESCALE_STATS(i, e_tmo),
|
|
IPFREESCALE_STATS(i, e_euerr),
|
|
IPFREESCALE_STATS(i, e_serr),
|
|
IPFREESCALE_STATS(i, e_derr),
|
|
IPFREESCALE_STATS(i, e_perr),
|
|
IPFREESCALE_STATS(i, e_tea));
|
|
|
|
|
|
if(ipcom_strcasecmp(where, "syslog") == 0)
|
|
{
|
|
IPCOM_LOG1(INFO, "%s", buf);
|
|
}
|
|
else if(ipcom_strcasecmp(where, "stdout") == 0)
|
|
{
|
|
ipcom_printf("%s\n", buf);
|
|
}
|
|
}
|
|
|
|
done:
|
|
if(buf != IP_NULL)
|
|
ipcom_free(buf);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_clear_stats
|
|
*===========================================================================
|
|
* Description: Clear SEC statistics
|
|
* Parameters: none.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_GLOBAL void
|
|
ipfreescale_coldfire_clear_stats(void)
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<IPFREESCALE_COLDFIRE_NUM_CHANNELS; i++)
|
|
ipcom_memset(&ipfreescale_coldfire.channel[i].stats, 0, sizeof(Ipfreescale_coldfire_stats));
|
|
}
|
|
#endif /* #ifdef IPFREESCALE_USE_STATISTICS */
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_init
|
|
*===========================================================================
|
|
* Description: Initialize SEC.
|
|
* Parameters: none.
|
|
* Returns: IPCOM_SUCCESS = ok.
|
|
* IPCOM_ERR_FAILED = error.
|
|
*/
|
|
IP_GLOBAL Ip_err
|
|
ipfreescale_coldfire_init(void)
|
|
{
|
|
Ip_err ret;
|
|
int i;
|
|
|
|
ipcom_memset(&ipfreescale_coldfire, 0, sizeof(ipfreescale_coldfire));
|
|
|
|
/* Create the channel resource mutex */
|
|
ret = ipcom_mutex_create(&ipfreescale_coldfire.chmtx);
|
|
if(ret != IPCOM_SUCCESS)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipfreescale_coldfire_init() :: Failed to create mutex");
|
|
goto fail;
|
|
}
|
|
|
|
ipfreescale_coldfire_regs();
|
|
if(ipfreescale_coldfire_reset() != 0)
|
|
{
|
|
IPCOM_LOG0(ERR, "ipfreescale_coldfire_init() :: Failed to reset SEC");
|
|
ret = IPCOM_ERR_FAILED;
|
|
goto fail;
|
|
}
|
|
|
|
/* Mask unwanted interrupts */
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrh, IPFREESCALE_COLDFIRE_SIMRH_AERR);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_TEA);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_DEUDN);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_DEUERR);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_AESUDN);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_AESUERR);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_MDEUDN);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_MDEUERR);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_AFEUDN);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_AFEUERR);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_RNGDN);
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrl, IPFREESCALE_COLDFIRE_SIMRL_RNGERR);
|
|
|
|
/* Initialize channels */
|
|
for(i=0; i<IPFREESCALE_COLDFIRE_NUM_CHANNELS; i++)
|
|
{
|
|
/* Mask channel error interrupt */
|
|
if(i == 0)
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrh, IPFREESCALE_COLDFIRE_SIMRH_CHA0ERR);
|
|
else if(i == 1)
|
|
IP_BIT_SET(*ipfreescale_coldfire.simrh, IPFREESCALE_COLDFIRE_SIMRH_CHA1ERR);
|
|
else
|
|
IP_PANIC();
|
|
|
|
/* Initialize channel */
|
|
if(ipfreescale_coldfire_channel_init(i) != 0)
|
|
{
|
|
IPCOM_LOG1(ERR, "ipfreescale_coldfire_init() :: Failed to initialize channel %d", i);
|
|
ret = IPCOM_ERR_FAILED;
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
/* Check processor type */
|
|
switch(*ipfreescale_coldfire.jtagid & IPFREESCALE_MCF_JTAGID_PROCESSOR)
|
|
{
|
|
case IPFREESCALE_MCF_JTAGID_MCF5485:
|
|
IPCOM_LOG0(INFO, "ipfreescale_start() :: Processor type is MCF5485.");
|
|
break;
|
|
case IPFREESCALE_MCF_JTAGID_MCF5475:
|
|
IPCOM_LOG0(INFO, "ipfreescale_start() :: Processor type is MCF5475.");
|
|
break;
|
|
default:
|
|
IPCOM_LOG0(WARNING, "ipfreescale_start() :: Processor type is unknown!");
|
|
break;
|
|
}
|
|
|
|
return IPCOM_SUCCESS;
|
|
|
|
fail:
|
|
if(ipfreescale_coldfire.chmtx != IP_NULL)
|
|
(void)ipcom_mutex_delete(&ipfreescale_coldfire.chmtx);
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_reserve_channel
|
|
*===========================================================================
|
|
* Description: Reserve a SEC channel.
|
|
* Parameters: none.
|
|
* Returns: channel number or -1 if failed.
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_reserve_channel(void)
|
|
{
|
|
int i, ch = -1;
|
|
|
|
ipcom_mutex_lock(ipfreescale_coldfire.chmtx);
|
|
for(i=0; i<IPFREESCALE_COLDFIRE_NUM_CHANNELS; i++)
|
|
{
|
|
if(ipfreescale_coldfire.channel[i].in_use == IP_FALSE)
|
|
{
|
|
/* Mark channel busy */
|
|
ipfreescale_coldfire.channel[i].in_use = IP_TRUE;
|
|
ch = i;
|
|
break;
|
|
}
|
|
}
|
|
ipcom_mutex_unlock(ipfreescale_coldfire.chmtx);
|
|
|
|
return ch;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_release_channel
|
|
*===========================================================================
|
|
* Description: Release a SEC channel.
|
|
* Parameters: ch - channel to release.
|
|
* Returns: nothing.
|
|
*/
|
|
IP_GLOBAL void
|
|
ipfreescale_coldfire_release_channel(int ch)
|
|
{
|
|
ipcom_mutex_lock(ipfreescale_coldfire.chmtx);
|
|
ipfreescale_coldfire.channel[ch].in_use = IP_FALSE;
|
|
ipcom_mutex_unlock(ipfreescale_coldfire.chmtx);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_engage
|
|
*===========================================================================
|
|
* Description: Engage a SEC channel. Launch descriptor to channel and wait
|
|
* for completion.
|
|
* Parameters: dp - pointer to SEC descriptor.
|
|
* ch - channel.
|
|
* peu - primary execution unit.
|
|
* seu - secondary execution unit.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_engage(Ipfreescale_coldfire_descriptor *dp, int ch, int peu, int seu)
|
|
{
|
|
int status;
|
|
|
|
switch(peu)
|
|
{
|
|
case IPFREESCALE_COLDFIRE_EU_AFEU:
|
|
IPFREESCALE_STATS(ch, u_afeu++);
|
|
break;
|
|
case IPFREESCALE_COLDFIRE_EU_DEU:
|
|
IPFREESCALE_STATS(ch, u_deu++);
|
|
break;
|
|
case IPFREESCALE_COLDFIRE_EU_MDEU:
|
|
IPFREESCALE_STATS(ch, u_mdeu++);
|
|
break;
|
|
case IPFREESCALE_COLDFIRE_EU_RNG:
|
|
IPFREESCALE_STATS(ch, u_rng++);
|
|
break;
|
|
case IPFREESCALE_COLDFIRE_EU_AESU:
|
|
IPFREESCALE_STATS(ch, u_aesu++);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if(seu == IPFREESCALE_COLDFIRE_EU_MDEU)
|
|
IPFREESCALE_STATS(ch, u_mdeu++);
|
|
|
|
ipfreescale_coldfire_channel_launch(ch, dp);
|
|
status = ipfreescale_coldfire_channel_waitforcompletion(ch);
|
|
if(status <= 0)
|
|
ipfreescale_coldfire_channel_error(status, ch, peu, seu);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_random_gen
|
|
*===========================================================================
|
|
* Description: Generate sequence of random data.
|
|
* Parameters: data - pointer to buffer for random data.
|
|
* length - number of bytes in sequence.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_random_gen(Ip_u8 *data, Ip_u32 length)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_random_gen() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
pmode = 0;
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_RNG,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_rng(data, length, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_RNG, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_md5_digest
|
|
*===========================================================================
|
|
* Description: Calculate message digest using the MD5 algorithm.
|
|
* Parameters: data - pointer to buffer with the data to hash.
|
|
* length - length of data in bytes.
|
|
* digest - pointer to buffer for the digest (16 bytes).
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_md5_digest(IP_CONST Ip_u8 *data, Ip_u32 length, Ip_u8 *digest)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_md5_digest() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
pmode = 1<<4; /* initialize */
|
|
pmode |= 1<<2; /* pad */
|
|
pmode |= 2; /* md5 */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_MDEU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_mdeu(data, length, digest, IPFREESCALE_MD5_DIGEST_SIZE, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_MDEU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_sha1_digest
|
|
*===========================================================================
|
|
* Description: Calculate message digest using the SHA1 algorithm.
|
|
* Parameters: data - pointer to buffer with the data to hash.
|
|
* length - length of data in bytes.
|
|
* digest - pointer to buffer for the digest (20 bytes).
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_sha1_digest(IP_CONST Ip_u8 *data, Ip_u32 length, Ip_u8 *digest)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_sha1_digest() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
pmode = 1<<4; /* initialize */
|
|
pmode |= 1<<2; /* pad */
|
|
pmode |= 0; /* sha1 */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_MDEU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_mdeu(data, length, digest, IPFREESCALE_SHA1_DIGEST_SIZE, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_MDEU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_des_cbc_cipher
|
|
*===========================================================================
|
|
* Description: Encrypt or decrypt a data buffer using DES-CBC cipher.
|
|
* Parameters: data - pointer to buffer with the data.
|
|
* length - length of data in bytes.
|
|
* key - pointer to buffer with the key (8 bytes).
|
|
* iv - Initialization vector (8 bytes). Updated by hardware.
|
|
* enc - 1 = encryption. 0 = decryption.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_des_cbc_cipher(Ip_u8 *out, IP_CONST Ip_u8 *in, Ip_u32 length, void *key, Ip_u8 *iv, int enc)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_des_cbc_cipher() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
pmode = 1<<2; /* cbc */
|
|
if(enc)
|
|
pmode |= 1; /* encrypt/decrypt */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_DEU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
|
|
#ifdef IPFREESCALE_COLDFIRE_FIX_DES_PARITY
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i=0; i<IPFREESCALE_DES_KEY_SIZE; i++)
|
|
((Ip_u8 *)key)[i] = ipfreescale_parity_odd[((Ip_u8 *)key)[i]];
|
|
}
|
|
#endif
|
|
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_deu_cbc(out, in, length, key, IPFREESCALE_DES_KEY_SIZE, iv, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_DEU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);;
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_des_ecb_cipher
|
|
*===========================================================================
|
|
* Description: Encrypt or decrypt a data buffer using DES-ECB cipher.
|
|
* Parameters: data - pointer to buffer with the data.
|
|
* length - length of data in bytes.
|
|
* key - pointer to buffer with the key (8 bytes).
|
|
* enc - 1 = encryption. 0 = decryption.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_des_ecb_cipher(Ip_u8 *out, IP_CONST Ip_u8 *in, Ip_u32 length, void *key, int enc)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_des_ecb_cipher() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
pmode = 0<<2; /* ecb */
|
|
if(enc)
|
|
pmode |= 1; /* encrypt/decrypt */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_DEU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
|
|
#ifdef IPFREESCALE_COLDFIRE_FIX_DES_PARITY
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i=0; i<IPFREESCALE_DES_KEY_SIZE; i++)
|
|
((Ip_u8 *)key)[i] = ipfreescale_parity_odd[((Ip_u8 *)key)[i]];
|
|
}
|
|
#endif
|
|
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_deu_ecb(out, in, length, key, IPFREESCALE_DES_KEY_SIZE, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_DEU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_3des_cbc_cipher
|
|
*===========================================================================
|
|
* Description: Encrypt or decrypt a data buffer using 3DES-CBC cipher.
|
|
* Parameters: data - pointer to buffer with the data.
|
|
* length - length of data in bytes.
|
|
* key - pointer to buffer with the key (24 bytes).
|
|
* iv - Initialization vector (8 bytes). Updated by hardware.
|
|
* enc - 1 = encryption. 0 = decryption.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_3des_cbc_cipher(Ip_u8 *out, IP_CONST Ip_u8 *in, Ip_u32 length, void *key, Ip_u8 *iv, int enc)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_3des_cbc_cipher() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
pmode = 1<<2; /* cbc */
|
|
pmode |= 1<<1; /* triple des */
|
|
if(enc)
|
|
pmode |= 1; /* encrypt/decrypt */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_DEU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
|
|
#ifdef IPFREESCALE_COLDFIRE_FIX_DES_PARITY
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i=0; i<IPFREESCALE_3DES_KEY_SIZE; i++)
|
|
((Ip_u8 *)key)[i] = ipfreescale_parity_odd[((Ip_u8 *)key)[i]];
|
|
}
|
|
#endif
|
|
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_deu_cbc(out, in, length, key, IPFREESCALE_3DES_KEY_SIZE, iv, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_DEU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_3des_ecb_cipher
|
|
*===========================================================================
|
|
* Description: Encrypt or decrypt a data buffer using 3DES-ECB cipher.
|
|
* Parameters: data - pointer to buffer with the data.
|
|
* length - length of data in bytes.
|
|
* key - pointer to buffer with the key (24 bytes).
|
|
* enc - 1 = encryption. 0 = decryption.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_3des_ecb_cipher(Ip_u8 *out, IP_CONST Ip_u8 *in, Ip_u32 length, void *key, int enc)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_3des_ecb_cipher() :: No channel available");
|
|
goto done;
|
|
}
|
|
/* Mode */
|
|
pmode = 0<<2; /* ecb */
|
|
pmode |= 1<<1; /* triple des */
|
|
if(enc)
|
|
pmode |= 1; /* encrypt/decrypt */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_DEU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
|
|
#ifdef IPFREESCALE_COLDFIRE_FIX_DES_PARITY
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i=0; i<IPFREESCALE_3DES_KEY_SIZE; i++)
|
|
((Ip_u8 *)key)[i] = ipfreescale_parity_odd[((Ip_u8 *)key)[i]];
|
|
}
|
|
#endif
|
|
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_deu_ecb(out, in, length, key, IPFREESCALE_3DES_KEY_SIZE, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_DEU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_aes_cbc_cipher
|
|
*===========================================================================
|
|
* Description: Encrypt or decrypt a data buffer using AES-CBC cipher.
|
|
* Parameters: data - pointer to buffer with the data.
|
|
* length - length of data in bytes.
|
|
* key - pointer to buffer with the key (16 bytes).
|
|
* iv - Initialization vector (16 bytes). Updated by hardware.
|
|
* enc - 1 = encryption. 0 = decryption.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_aes_cbc_cipher(Ip_u8 *out, IP_CONST Ip_u8 *in, Ip_u32 length, void *key, Ip_u32 keylen, Ip_u8 *iv, int enc)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_aes_cbc_cipher() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
pmode = 1<<1; /* cbc */
|
|
if(enc)
|
|
pmode |= 1; /* encrypt/decrypt */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_AESU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_aesu_cbc(out, in, length, key, keylen, iv, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_AESU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_aes_ecb_cipher
|
|
*===========================================================================
|
|
* Description: Encrypt or decrypt a data buffer using AES-ECB cipher.
|
|
* Parameters: data - pointer to buffer with the data.
|
|
* length - length of data in bytes.
|
|
* key - pointer to buffer with the key (16 bytes).
|
|
* enc - 1 = encryption. 0 = decryption.
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_aes_ecb_cipher(Ip_u8 *out, IP_CONST Ip_u8 *in, Ip_u32 length, void *key, Ip_u32 keylen, int enc)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_aes_ecb_cipher() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
pmode = 0<<1; /* cbc */
|
|
if(enc)
|
|
pmode |= 1; /* encrypt/decrypt */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_AESU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_NO_AFEU,
|
|
&descr);
|
|
/* Load descriptor */
|
|
ipfreescale_coldfire_descr_load_aesu_ecb(out, in, length, key, keylen, &descr);
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_AESU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipfreescale_coldfire_rc4_cipher
|
|
*===========================================================================
|
|
* Description: RC4 stream cipher. Provide either key + output context
|
|
* for operation with key load and context save or input context +
|
|
* output context for operation with context load and context save.
|
|
* Parameters: data - pointer to buffer with the data to cipher.
|
|
* length - length of data in bytes.
|
|
* key - pointer to buffer with the key.
|
|
* keylen - length of encryption key (1-16 bytes).
|
|
* ctxi - buffer with input context (259 bytes).
|
|
* ctxo - buffer with output context (259 bytes).
|
|
* Returns: -1 = error
|
|
* 0 = timeout
|
|
* 1 = ok
|
|
*/
|
|
IP_GLOBAL int
|
|
ipfreescale_coldfire_rc4_cipher(Ip_u8 *out, IP_CONST Ip_u8 *in, Ip_u32 length, void *key, Ip_u32 keylen, Ip_u8 *ctxi, Ip_u8 *ctxo)
|
|
{
|
|
Ipfreescale_coldfire_descriptor descr;
|
|
int ch, pmode = 0, ret = -1;
|
|
|
|
/* Acquire a crypto channel */
|
|
ch = ipfreescale_coldfire_reserve_channel();
|
|
if(ch < 0)
|
|
{
|
|
IPCOM_LOG0(INFO, "ipfreescale_coldfire_rc4_cipher() :: No channel available");
|
|
goto done;
|
|
}
|
|
|
|
/* Mode */
|
|
if(ctxi != IP_NULL)
|
|
{
|
|
pmode += 1; /* prevent permute */
|
|
pmode += 1<<2; /* context from input fifo */
|
|
}
|
|
pmode += 1<<1; /* dump context */
|
|
|
|
/* Create descriptor */
|
|
ipfreescale_coldfire_descr_create(IPFREESCALE_COLDFIRE_EU_AFEU,
|
|
pmode,
|
|
IPFREESCALE_COLDFIRE_COMMON_NONSNOOP_AFEU,
|
|
&descr);
|
|
/* Load descriptor */
|
|
if(key != IP_NULL)
|
|
ipfreescale_coldfire_descr_load_afeu(out, in, length, key, keylen, IP_NULL, ctxo, &descr);
|
|
else if(ctxi != IP_NULL)
|
|
ipfreescale_coldfire_descr_load_afeu(out, in, length, IP_NULL, 0, ctxi, ctxo, &descr);
|
|
else
|
|
{
|
|
IP_PANIC();
|
|
goto done;
|
|
}
|
|
|
|
/* Engage crypto hardware */
|
|
ipfreescale_coldfire_flush_descriptor(&descr);
|
|
ret = ipfreescale_coldfire_engage(&descr, ch, IPFREESCALE_COLDFIRE_EU_AFEU, IPFREESCALE_COLDFIRE_EU_NONE);
|
|
|
|
done:
|
|
/* Release the crypto channel */
|
|
if(ch >= 0)
|
|
ipfreescale_coldfire_release_channel(ch);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
#else
|
|
int ipfreescale_coldfire_empty_file;
|
|
#endif /* #ifdef IPFREESCALE_COLDFIRE */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|