Files
m241Neelima/components/ip_net2-6.9/ipfreescale/sec4/sec4_qi_request.c
T
2026-07-30 11:19:44 +05:30

1237 lines
50 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: sec4_qi_request.c,v $ $Revision: 1.5 $
* $Source: /home/interpeak/CVSRoot/ipfreescale/sec4/sec4_qi_request.c,v $
* $Author: dhessing $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/****************************************************************************
* sec4_qi_request.c - request/response handler for SEC4 jobs via its queue
* interface.
* To allow to setup shared descriptors for IPsec SA that is maintained in a
* cache. Jobs for an IPsec SA is sent on a dedicated frame queue to return
* the job to the submitting core for post processing.
****************************************************************************
***************************************************************************/
#ifdef SEC4_USE_QI
/* Revision History:
* 1.0 First version.
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#include <vxWorks.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <memLib.h>
#include <semLib.h>
#include <taskLib.h>
#include <vxCpuLib.h>
#include <vxBusLib.h>
#include <cpuset.h>
#include <hwif/vxbus/vxBus.h>
#include <hwif/util/vxbParamSys.h>
#include <../src/hwif/h/resource/vxbQorIQQmanPortal.h>
#include <../src/hwif/h/resource/vxbQorIQBmanPortal.h>
#include <sec_dcl_ext.h>
#include <sec_qi_ext.h>
#include <sec_dcl_ipfreescale.h>
#include "Sec4Driver.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* Define module for errors reported from this file (as used in SEC4 driver) */
#define __ERR_MODULE__ MODULE_SEC
/* TODO: This should be in vxbQorIQQmanPortal.h */
#define SEC4_QPORTAL_CHAN_SEC4 (0x80)
#define SEC4_QPORTAL_WQ_0 (0x0)
/* "Split keys" are used by SEC4 HMAC to increase performance on crypto operations.
* Required for SEC4 IPsec protocol processing */
#define SEC4_MD5_SPLIT_KEY_SIZE (32)
#define SEC4_SHA1_SPLIT_KEY_SIZE (40)
#define SEC4_IPSEC_INIT_SEQ_NO (2)
/* Scatter gather table defines */
#define SEC4_SGT_LENGTH_MASK 0x3FFFFFFF
#define SEC4_SGT_OFFSET_MASK 0x1FFF
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/* Scatter gather table used for submitting compound frames to SEC4 */
typedef struct t_sec4IpsecSgTbl
{
QPORTAL_SGLIST out;
QPORTAL_SGLIST in;
} t_sec4IpsecSgTbl;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
int sec4_ipsec_outbound_request(uint8_t *buf, uint16_t inOffset, uint16_t length, uint16_t outOffset,
t_sec4IpsecSa *sec4IpsecSa, uint16_t saIndex,
uint8_t poolId);
int sec4_ipsec_inbound_request(uint8_t *buf, uint16_t inOffset, uint16_t length, uint16_t outOffset,
t_sec4IpsecSa *sec4IpsecSa, uint16_t saIndex,
uint8_t poolId);
t_Handle sec4_ipsec_create_shr_desc(t_sec4IpsecSa *sec4IpsecSa,
uint32_t fqIx, uint8_t enc);
int sec4_create_split_key(uint8_t *p_InputKey, uint8_t *p_OutputKey, e_IpsecAuthenAlg hashAlg);
void * sec4_buf_alloc(uint8_t poolId);
int sec4_qi_enqueue(t_sec4IpsecSgTbl *sgTbl, uint32_t fqId);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/* Global handles */
SEC4_GLOBAL t_Handle h_Sec4;
SEC4_GLOBAL t_Handle h_SecQi;
SEC4_GLOBAL t_Handle h_SecDclQi;
SEC4_GLOBAL t_Handle h_SecJobQueue;
static QPORTAL *sec4Qportal = NULL; /* QMAN portal to enqueue jobs to. Must be set by user via public function */
static BPORTAL *sec4Bportal = NULL; /* BMAN portal to allocate SGT buffers from. Must be set by user via public function */
static uint8_t sec4SgtPoolId = 0; /* BMAN buffer pool ID to allocate SGT buffers from. Must be set by user via public function */
/* SEC4 SA cache */
SEC4_GLOBAL t_Handle h_sec4IpsecSaCache;
SEC4_GLOBAL uint32_t sec4IpsecSaCacheNoofEntries;
/* Shared memory */
SEC4_GLOBAL t_Handle h_sec4Shm;
/* Frame queues to use */
static uint32_t sec4QmanEnqueueFqidBase = 0; /* Frame queue ID base for jobs submitted to the SEC4. Must be set by user via public function */
static uint32_t sec4QmanDequeueDecryptFqidBase = 0; /* Frame queue ID base for completed jobs from SEC4. Must be set by user via public function */
static uint32_t sec4QmanDequeueEncryptFqidBase = 0; /* Frame queue ID base for completed jobs from SEC4. Must be set by user via public function */
/* Shared(between cores) map of SA->FQ ID */
SEC4_GLOBAL uint32_t **sec4IpsecSaFqMap;
#ifdef SEC4_USE_SHARED_JOB_QUEUE
/* Core to core communication vector */
/* First core will handle all interrupt from the shared job queue.
* It will notify other cores of a completed job via this vector. One entry per core */
SEC4_GLOBAL t_sec4IpcMsg *sec4IpcVector;
#endif
SEC4_GLOBAL uint32_t sec4CoreId;
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* sec4unlock
*===========================================================================
* Description: Release semaphore held during internal job submission to job
* queues.
*
* Parameters: -
* Returns: -
*/
void sec4unlock(void)
{
IOUnLockJobEnqueue();
}
/* TODO: Cleanup the dependency towards ipcom */
/*
*===========================================================================
* sec4spinLockLock
*===========================================================================
* Description: Spin lock to protect a resource from any other core.
*
* Parameters: lock - identifier for the lock
* Returns: -
*/
void sec4spinLockLock(uint32_t lock)
{
ipcom_enter_critical_region_no(lock);
}
/*
*===========================================================================
* sec4unlock
*===========================================================================
* Description: Unlock a lock previously locked by sec4spinLockLock.
*
* Parameters: lock - identifier for the lock
* Returns: -
*/
void sec4spinLockUnlock(uint32_t lock)
{
ipcom_exit_critical_region_no(lock);
}
/*
*===========================================================================
* sec4_buf_alloc
*===========================================================================
* Description: Allocate BMAN buffer from sec4Bportal
*
* Parameters: 'poolId' : BMAN pool ID to allocate buffer from
* Returns: Buffer address or NULL if no buffer can be allocated
*/
void * sec4_buf_alloc(uint8_t poolId)
{
uint32_t s;
physAddress_t paddr;
s = XX_DisableAllIntr();
if(bportalAlloc(sec4Bportal, poolId, &paddr) != OK)
{
XX_RestoreAllIntr(s);
return NULL;
}
XX_RestoreAllIntr(s);
//return XX_PhysToVirt(paddr);
return XX_PhysToVirt((physAddress_t)((uint32_t)paddr)); /* TODO Some buffer pointers in IPCOM_P4080_COMMON_POOL are corrupted */
}
/*
*===========================================================================
* sec4_qi_enqueue
*===========================================================================
* Description: Enqueue a compund frame to QMAN
*
* Parameters: 'sgTbl' : Scatter gather table for the compound frame
* Returns: E_OK if ok. Otherwise E_FULL
*/
int sec4_qi_enqueue(t_sec4IpsecSgTbl *sgTbl, uint32_t fqId)
{
QPORTAL_FDESC qpfd;
physAddress_t p_phys;
p_phys = XX_VirtToPhys(sgTbl);
qpfd.qportalDdLioLo = 0;
qpfd.qportalLioHi = 0;
qpfd.qportalBpid = (UINT8) sec4SgtPoolId;
qpfd.qportalAddrHi = (UINT8) (((UINT64)((UINT64) (p_phys)) >> 32) & 0xFFFFFFFF);
qpfd.qportalAddrLo = (UINT32) ((UINT64)((UINT64) (p_phys)) & 0xFFFFFFFF);
qpfd.qportalCmd = 0;
qpfd.qportalOffLen = (UINT32) (QPORTAL_FDESC_FMT_COMPOUND | (sizeof(t_sec4IpsecSgTbl) & QPORTAL_FDESC_OFFLEN_LENGTH));
/* Enqueue to Qman */
if(qportalSafeEnqueue (sec4Qportal, fqId, 0, &qpfd) != OK)
{
SEC4Dump(DBGTXT_ERROR,("sec4_qi_enqueue() :: qportalEnqueue returned error. fqId=0x%x\n", fqId));
return ERROR_CODE(E_FULL);
}
SEC4Dump(DBGTXT_SVCRQ,("sec4_qi_enqueue() :: qpfd.qportalDdLioLo=%d, qpfd.qportalBpid=0x%x, qpfd.qportalAddrHi=0x%x, qpfd.qportalAddrLo=0x%x, qpfd.qportalCmd=0x%x, qpfd.qportalOffLen=0x%x\n",\
qpfd.qportalDdLioLo, qpfd.qportalBpid, qpfd.qportalAddrHi, qpfd.qportalAddrLo,qpfd.qportalCmd, qpfd.qportalOffLen));
return E_OK;
}
/*
*===========================================================================
* sec4_create_split_key
*===========================================================================
* Description: Pre-computes a SEC4 "split key" as is requred for IPsec protocol
* operation. Each shared descriptor will need to create split
* key for the authentication keys. This is to increase
* performance for the SEC4 MDHA CHA.
* The split key is encrypted and will be decrypted by SEC4 on usage.
*
* Parameters: 'p_InputKey' : Input key as specified in the SA
* 'p_OutputKey' : Split key
* 'hashAlg' : Hash algorithm to create split key for
* Returns: length of split key if ok, 0 otherwise
*
*/
int sec4_create_split_key(uint8_t *p_InputKey, uint8_t *p_OutputKey, e_IpsecAuthenAlg hashAlg)
{
int splitKeyLength;
t_Handle h_JobDesc;
t_SplitKeyJobDescParam splitKeyJobDescParam;
int status;
t_Handle h_Context;
int len;
GENERIC_REQ *req;
#ifdef SEC4_USE_SHARED_JOB_QUEUE
req = XX_MallocSmart(sizeof(GENERIC_REQ), 1, 1);
#else
req = XX_Malloc(sizeof(GENERIC_REQ));
#endif
switch(hashAlg)
{
case e_IPSEC_AUTHEN_ALG_HMAC_MD5_96:
splitKeyJobDescParam.hashAlg = e_SPLIT_KEY_HASH_ALG_MD5;
len = SEC4_MD5_SPLIT_KEY_SIZE;
break;
case e_IPSEC_AUTHEN_ALG_HMAC_SHA1_96:
splitKeyJobDescParam.hashAlg = e_SPLIT_KEY_HASH_ALG_SHA1;
len = SEC4_SHA1_SPLIT_KEY_SIZE;
break;
default:
SEC4Dump(DBGTXT_ERROR,("sec4_create_split_key() :: Unsupported hash alg: %d\n", hashAlg));
return 0;
}
splitKeyJobDescParam.p_InputKey = p_InputKey;
splitKeyJobDescParam.p_OutputKey = p_OutputKey;
h_JobDesc = SEC_DCL_InitSplitKeyJobDesc(h_SecDclQi, &splitKeyJobDescParam);
if(h_JobDesc == NULL)
{
SEC4Dump(DBGTXT_ERROR,("sec4_create_split_key() :: Error creating descriptor\n"));
return 0;
}
SEC4DbgDo(DBGTXT_DESCSHOW, SEC_DCL_DebugPrintDescriptor((t_Desc *)h_JobDesc));
/* Prepare a request structure */
req->jobDesc = h_JobDesc;
req->notify = &sec4unlock; /* Release semaphore when job has completed */
req->notify_on_error = &sec4unlock;
req->opId = DPD_SEC4_INTERNAL_CMN;
req->status = 0;
req->ctxNotifyOnErr.request = req;
req->ctxNotifyOnErr.errorcode = 0;
req->pNotifyCtx = req;
req->notifyFlags = 0;
/* Enqueue job on SEC4 job queue */
h_Context = (t_Handle) req;
IOLockJobEnqueue(); /* Don't release the lock. It is released when job is completed */
#ifdef SEC4_USE_SHARED_JOB_QUEUE
sec4IpcVector[sec4CoreId].state = SEC4_IPC_STATE_PENDING;
sec4IpcVector[sec4CoreId].req = req;
/* Update core ID in request to be able to get the job back to the same core */
req->coreId = sec4CoreId;
/* Protect the shared job queue while enqueueing job */
sec4spinLockLock(SEC4_SH_JQ_SPINLOCK_ID);
#endif
status = SEC_JQ_Enqueue(h_SecJobQueue, (void *) ((t_Desc *)h_JobDesc)->p_Buffer, h_Context);
#ifdef SEC4_USE_SHARED_JOB_QUEUE
sec4spinLockUnlock(SEC4_SH_JQ_SPINLOCK_ID);
#endif
if(E_OK != status)
{
SEC4Dump(DBGTXT_ERROR,("sec4_create_split_key() :: Error: 0x%x, from SEC_JQ_Enqueue\n", status));
SEC_DCL_FreeDesc(h_JobDesc);
return 0;
}
/* Wait for lock to be released when job is completed by trying to get it again */
IOLockJobEnqueue();
IOUnLockJobEnqueue();
/* Check status of job */
if(req->status == SEC4_JOB_ERROR)
{
SEC4Dump(DBGTXT_ERROR,("sec4_create_split_key() :: Error: 0x%x, received from SEC engine\n", req->ctxNotifyOnErr.errorcode));
return 0;
}
XX_FreeSmart(req);
SEC4Dump(DBGTXT_SETRQ, ("sec4_create_split_key() :: Successfully generated split key of length=%d\n", len));
return len;
}
/*
*===========================================================================
* sec4_ipsec_assign_fq
*===========================================================================
* Description: Assigns a frame queue to use a shared descriptor.
*
* Parameters: 'h_JobDesc' : IPsec shared descriptor handle
* 'fqIx' : Frame queue index to use for this SA
*
* Returns: handle to the shared descriptor if ok, otherwise NULL
*
*/
int sec4_ipsec_assign_fq(t_Handle h_JobDesc, uint32_t fqIx, uint8_t enc)
{
t_SecPreHeader *p_PreHeader;
uint32_t fqId;
physAddress_t p;
uint32_t qmanDequeueFqId;
/* Add SEC QI pre-header */
p_PreHeader = (t_SecPreHeader *) SEC_DCL_GetDescPrefix(h_JobDesc);
SEC_PH_SET_RSLS(p_PreHeader, 0);
SEC_PH_SET_SDLEN(p_PreHeader, SEC_DCL_GetBufferSize(h_JobDesc) / sizeof(uint32_t));
SEC_PH_SET_FSGT(p_PreHeader, 0);
SEC_PH_SET_LONG(p_PreHeader, 0);
SEC_PH_SET_OFFSET(p_PreHeader, 0);
SEC_PH_SET_ABS(p_PreHeader, 0);
SEC_PH_SET_ADDBUF(p_PreHeader, 0);
SEC_PH_SET_POOLID(p_PreHeader, 0); /* 0 = Use the input buffer for output as well */
SEC_PH_SET_BUFSIZE(p_PreHeader, 0);
/* Print pre header */
SEC4DbgDo(DBGTXT_DESCSHOW, SEC_DCL_DebugPrintPreHeader((t_SecPreHeader *)p_PreHeader));
/* Add frame queue for this SA. Transmit on this queue */
/* fqId needs to be unique per SA since the pre-header (ctxA) and frame descriptor is unique per FQ */
fqId = sec4QmanEnqueueFqidBase + fqIx;
SEC4Dump(DBGTXT_SETRQ,("sec4_ipsec_assign_fq() :: fqId=0x%x\n", fqId));
/* SEC4 require that for qportalFqInit:
* ctxB = FQID to use when enqueueing frame descriptors for completed jobs
* ctxA = pointer to pre header */
p = XX_VirtToPhys(p_PreHeader);
if(enc != 0)
qmanDequeueFqId = sec4QmanDequeueEncryptFqidBase + fqIx;
else
qmanDequeueFqId = sec4QmanDequeueDecryptFqidBase + fqIx;
if( qportalFqInit (sec4Qportal, fqId,
SEC4_QPORTAL_CHAN_SEC4,
SEC4_QPORTAL_WQ_0,
qmanDequeueFqId,
(UINT16)(((uint64_t)p) >> 32), (UINT32) p, 0) != OK)
{
SEC4Dump(DBGTXT_ERROR,("sec4_ipsec_assign_fq() :: qportalFqInit returned error sec4Qportal=0x%x, fqId=0x%x, qmanDequeueFqId=0x%x\n", sec4Qportal, fqId, qmanDequeueFqId));
return -1; /* TODO */
}
/* Assign FQID to MAP */
sec4IpsecSaFqMap[fqIx][sec4CoreId] = fqId;
return E_OK;
}
/*
*===========================================================================
* sec4_ipsec_free_fq
*===========================================================================
* Description: Shut down and release a frame queue.
*
* Parameters: 'fqId' : Frame queue id to release
*
* Returns: E_OK if ok, otherwise Error code
*
*/
int sec4_ipsec_free_fq(uint32_t fqId)
{
QPORTAL_QUERYFQ_NP_RESP fqStatusResponse;
/* Query frame queue to detect if previously setup, then shut it down */
if( qportalFqNpQuery(sec4Qportal, fqId, &fqStatusResponse) != OK)
{
SEC4Dump(DBGTXT_ERROR,("sec4_ipsec_free_fq() :: qportalFqNpQuery returned error sec4Qportal=0x%x, fqId=0x%x\n", sec4Qportal, fqId));
return ERROR_CODE(E_NOT_AVAILABLE);
}
if(fqStatusResponse.qportalState != 0) /* 0 = Out of Service */
{
/* The frame queue has been previously setup, shut it down first */
SEC4Dump(DBGTXT_SETRQ,("sec4_ipsec_free_fq() :: fqId=0x%x previously setup. Shutting it down\n", fqId));
if(qportalFqShutdown(sec4Qportal, fqId) != 0)
{
SEC4Dump(DBGTXT_ERROR,("sec4_ipsec_free_fq() :: qportalFqShutdown returned error sec4Qportal=0x%x, fqId=0x%x\n", sec4Qportal, fqId));
return ERROR_CODE(E_NOT_AVAILABLE);
}
}
return E_OK;
}
/*
*===========================================================================
* sec4_ipsec_create_shr_desc
*===========================================================================
* Description: Creates a shared descriptor and initialize a frame queue for
* an SA. The frame queue index must not already be in use.
*
* Parameters: 'sec4IpsecSa' : SA structure
* 'fqIx' : Frame queue index to use for this SA
* 'enc' : 1=encrypt(outbound), 0=decrypt(inbound)
*
* Returns: handle to the shared descriptor if ok, otherwise NULL
*
*/
t_Handle sec4_ipsec_create_shr_desc(t_sec4IpsecSa *sec4IpsecSa, uint32_t fqIx, uint8_t enc)
{
t_Handle h_JobDesc;
t_IpsecShrDescParam shrDescParam;
union {
t_IpsecEncapParam encapParam;
t_IpsecDecapParam decapParam;
} dclParam;
/* Prepare shared descriptor parameters */
shrDescParam.authenAlg = sec4IpsecSa->authAlg;
shrDescParam.cryptoAlg = sec4IpsecSa->cryptoAlg;
shrDescParam.authenKey.imm = sec4IpsecSa->authKey.imm;
shrDescParam.authenKey.p_Data = sec4IpsecSa->splitKey;
shrDescParam.authenKey.size = sec4IpsecSa->splitKeySize;
shrDescParam.cryptoKey.imm = sec4IpsecSa->cryptoKey.imm;
shrDescParam.cryptoKey.p_Data = sec4IpsecSa->cryptoKey.p_Data;
shrDescParam.cryptoKey.size = sec4IpsecSa->cryptoKey.size;
shrDescParam.dataMoveSize = 0; /* No data should be moved untouched to output frame */
if(enc == 1) /* Encrypt (Outbound) */
{
shrDescParam.dataMoveSize = SEC4_IPSEC_ESP_HEADER_SZ; /* ESP header untouched to output frame */
switch(sec4IpsecSa->cryptoAlg)
{
case e_IPSEC_CRYPTO_ALG_3DES:
shrDescParam.dataMoveSize += SEC4_IPSEC_ESP_DES_IV_SZ;
break;
case e_IPSEC_CRYPTO_ALG_AES_CBC:
shrDescParam.dataMoveSize += SEC4_IPSEC_ESP_AES_IV_SZ;
break;
}
/* Currently only CBC modes is supported */
dclParam.encapParam.ipsecType = e_IPSEC_TYPE_CBC;
memcpy(dclParam.encapParam.alg.cbc.iv, sec4IpsecSa->iv, sizeof(dclParam.encapParam.alg.cbc.iv));
dclParam.encapParam.randIv = FALSE; /* Use IV from descriptor PDB */
dclParam.encapParam.seqNum = SEC4_IPSEC_INIT_SEQ_NO; /* Initial sequence number for this SA */
dclParam.encapParam.extSeqNum = FALSE;
dclParam.encapParam.ipsecMode = sec4IpsecSa->ipsecMode;
dclParam.encapParam.ipsecVer = sec4IpsecSa->ipsecVer;
dclParam.encapParam.spi = sec4IpsecSa->spi;
dclParam.encapParam.ipHdrLen = 0; /* Packets should be pointer to inner IP header,
e.g. all data should be encrypted */
dclParam.encapParam.ipsecHdr = e_IPSEC_HDR_NONE; /* No outer IP header provided */
/* As no outer IP header should be provided in the packets
* SEC4 should not update any outer IP header fields */
dclParam.encapParam.nextHdr = (sec4IpsecSa->ipsecVer == e_IPSEC_VER_6)? 41: 4; /* ESP trailer next protocol */
dclParam.encapParam.nhOffset = 0;
dclParam.encapParam.p_IpHdr = NULL; /* User should add outer IP header */
dclParam.encapParam.copyDf = FALSE;
dclParam.encapParam.copyDs = FALSE;
dclParam.encapParam.decTtl = FALSE;
dclParam.encapParam.enCksm = FALSE;
/* Create seq descriptor */
h_JobDesc = SEC_DCL_InitIpsecEncapShrDescNoProto(h_SecDclQi,
&shrDescParam,
&dclParam.encapParam);
}
else /* Decrypt (Inbound) */
{
dclParam.decapParam.decTtl = FALSE;
dclParam.decapParam.copyDs = FALSE;
dclParam.decapParam.enCksm = FALSE;
dclParam.decapParam.extSeqNum = FALSE;
dclParam.decapParam.outFmt = TRUE; /* Strip outer IP and ESP header */
dclParam.decapParam.ipHdrLen = 0;
dclParam.decapParam.nhOffset = 0;
dclParam.decapParam.seqNum = SEC4_IPSEC_INIT_SEQ_NO; /* Initial sequence number for this SA */
dclParam.decapParam.ipsecArs = e_IPSEC_ARS_0; /* No HW supported anti-replay check */
dclParam.decapParam.ipsecVer = sec4IpsecSa->ipsecVer;
dclParam.decapParam.ipsecMode = sec4IpsecSa->ipsecMode;
dclParam.decapParam.ipsecType = e_IPSEC_TYPE_CBC;
/* Create seq descriptor */
h_JobDesc = SEC_DCL_InitIpsecDecapShrDescNoProto(h_SecDclQi,
&shrDescParam,
&dclParam.decapParam);
}
if(h_JobDesc == NULL)
{
SEC4Dump(DBGTXT_ERROR,("sec4_ipsec_create_shr_desc() :: Error creating descriptor\n"));
return NULL;
}
/* Print descriptor */
SEC4DbgDo(DBGTXT_DESCSHOW, SEC_DCL_DebugPrintDescriptor((t_Desc *)h_JobDesc));
SEC4Dump(DBGTXT_SETRQ,("sec4_ipsec_create_shr_desc() :: OK. h_JobDesc=0x%x\n", h_JobDesc));
return h_JobDesc;
}
/*
*===========================================================================
* sec4_ipsec_delete_shr_desc
*===========================================================================
* Description: Release and clear all resources used by an SEC4 IPsec SA.
*
* Parameters: 'sec4IpsecSa' : SEC4 IPsec SA
*
* Returns: E_OK if ok, otherwise error code
*
*/
int sec4_ipsec_delete_shr_desc(t_sec4IpsecSa *sec4IpsecSa)
{
/* Free shared descriptor and clear SA */
SEC_DCL_FreeDesc(sec4IpsecSa->h_ShrJobDesc);
memset(sec4IpsecSa, 0, sizeof(t_sec4IpsecSa));
return E_OK;
}
/*
*===========================================================================
* sec4_ipsec_outbound_request
*===========================================================================
* Description: Submits a IPsec outbound (encrypt) job to the SEC4 engine.
* The job is submitted as a compound frame, i.e. a scatter
* gather table in a separately allocated buffer with reference
* to the packet buffer as required by the SEC4 for protocol
* (IPsec) processing.
*
* Parameters: 'buf' : Pointer to memory buffer with packet
* 'inOffset' : Offset in bytes to first byte to encrypt
* 'length' : Number of bytes to encrypt
* TODO: Currently assume ipcom forwarder behaviour that padding and ESP trailer is part of 'length'.
* 'outOffset' : Offset in bytes to where SEC4 will store the encrypted data
* 'sec4IpsecSa' : IPsec SA
* 'saIndex' : IPsec SA index to use
* 'poolId' : Memory buffer pool ID for packet
*
* Returns: E_OK if ok, otherwise error code
*
*/
int sec4_ipsec_outbound_request(uint8_t *buf, uint16_t inOffset, uint16_t length, uint16_t outOffset,
t_sec4IpsecSa *sec4IpsecSa, uint16_t saIndex,
uint8_t poolId)
{
physAddress_t p_phys;
t_sec4IpsecSgTbl *sgTbl;
uint32_t fqIx = (uint32_t) saIndex; /* Frame queue index */
uint8_t *p = (uint8_t *)((uint32_t)buf + inOffset);
int status;
int padBytes;
SEC4Dump(DBGTXT_SETRQ, ("sec4_ipsec_outbound_request() : buf=0x%x, inOffset=%d, p=0x%x, length=%d, outOffset=%d, sec4IpsecSa=0x%x, saIndex=0x%x\n", buf, inOffset, p, length, outOffset, sec4IpsecSa, saIndex));
/* Prepare Scatter/Gather Table
* SEC4 require a 2 entry SG table in a compund frame to be able to modify a single buffer
* QMAN will create a Sequence descriptor from this info and the FQ pre-header and shared descriptor*/
sgTbl = sec4_buf_alloc(sec4SgtPoolId);
if(sgTbl == NULL)
{
SEC4Dump(DBGTXT_ERROR,("sec4_ipsec_outbound_request() :: Error: No buffer for SG table in pool=0x%x\n", sec4SgtPoolId));
return ERROR_CODE(E_NO_MEMORY);
}
/* TODO: ipcom_forwarder has already added padding and ESP trailer. Use this known implicit knowledge for now */
p_phys = XX_VirtToPhys((void *)((uint32_t)buf));
sgTbl->in.qportalAddrHi = (UINT8) (((UINT64)((UINT64) (p_phys)) >> 32) & 0xFFFFFFFF);
sgTbl->in.qportalAddrLo = (UINT32) ((UINT64)((UINT64) (p_phys)) & 0xFFFFFFFF);
sgTbl->in.qportalBpid = poolId;
sgTbl->in.qportalLength = (length & SEC4_SGT_LENGTH_MASK) | QPORTAL_SGLIST_FINAL;
sgTbl->in.qportalOffset = (UINT16) (inOffset & SEC4_SGT_OFFSET_MASK);
sgTbl->out.qportalAddrHi = sgTbl->in.qportalAddrHi;
sgTbl->out.qportalAddrLo = sgTbl->in.qportalAddrLo;
sgTbl->out.qportalOffset = (UINT16) (outOffset & SEC4_SGT_OFFSET_MASK);
sgTbl->out.qportalBpid = (UINT16) poolId;
/* Output start is at start of payload, output length = payload length + ICV */
sgTbl->out.qportalLength = (length & SEC4_SGT_LENGTH_MASK) + SEC4_IPSEC_ESP_ICV_SZ;
sgTbl->out.qportalOffset += SEC4_IPSEC_ESP_HEADER_SZ;
/* In offset to start of ESP packet */
sgTbl->in.qportalOffset -= SEC4_IPSEC_ESP_HEADER_SZ;
sgTbl->in.qportalLength += SEC4_IPSEC_ESP_HEADER_SZ;
/* Add algorithm dependant IV length */
switch(sec4IpsecSa->cryptoAlg)
{
case e_IPSEC_CRYPTO_ALG_3DES:
sgTbl->out.qportalOffset += SEC4_IPSEC_ESP_DES_IV_SZ;
sgTbl->in.qportalLength += SEC4_IPSEC_ESP_DES_IV_SZ;
sgTbl->in.qportalOffset -= SEC4_IPSEC_ESP_DES_IV_SZ;
break;
case e_IPSEC_CRYPTO_ALG_AES_CBC:
sgTbl->out.qportalOffset += SEC4_IPSEC_ESP_AES_IV_SZ;
sgTbl->in.qportalLength += SEC4_IPSEC_ESP_AES_IV_SZ;
sgTbl->in.qportalOffset -= SEC4_IPSEC_ESP_AES_IV_SZ;
break;
default:
/* Unsupported alg */
return ERROR_CODE(E_INVALID_ID);
}
SEC4Dump(DBGTXT_SVCRQ,("sgTbl->out.qportalAddrHi=0x%x, sgTbl->out.qportalAddrLo=0x%x, sgTbl->out.qportalBpid=%d, sgTbl->out.qportalLength=0x%x, sgTbl->out.qportalOffset=%d\n",\
sgTbl->out.qportalAddrHi, sgTbl->out.qportalAddrLo, sgTbl->out.qportalBpid, sgTbl->out.qportalLength, sgTbl->out.qportalOffset));
SEC4Dump(DBGTXT_SVCRQ,("sgTbl->in.qportalAddrHi=0x%x, sgTbl->in.qportalAddrLo=0x%x, sgTbl->in.qportalBpid=%d, sgTbl->in.qportalLength=0x%x, sgTbl->in.qportalOffset=%d\n",\
sgTbl->in.qportalAddrHi, sgTbl->in.qportalAddrLo, sgTbl->in.qportalBpid, sgTbl->in.qportalLength, sgTbl->in.qportalOffset));
/* Enqueue on queue Interface */
if(status = sec4_qi_enqueue(sgTbl, sec4IpsecSaFqMap[saIndex][sec4CoreId]) != E_OK)
{
SEC4Dump(DBGTXT_ERROR,("sec4_ipsec_outbound_request() :: qportalEnqueue returned error. fqId=0x%x\n", sec4IpsecSaFqMap[saIndex][sec4CoreId]));
return status;
}
SEC4Dump(DBGTXT_SVCRQ,("sec4_ipsec_outbound_request() :: p=0x%x enqueued on fqId=0x%x\n", p, sec4IpsecSaFqMap[saIndex][sec4CoreId]));
return E_OK;
}
/*
*===========================================================================
* sec4_ipsec_inbound_request
*===========================================================================
* Description: Submits a IPsec inbound (decrypt) job to the SEC4 engine.
* The job is submitted as a compound frame, i.e. a scatter
* gather table in a separately allocated buffer with reference
* to the packet buffer as required by the SEC4 for protocol
* (IPsec) processing.
* The SG table buffer is allocated from sec4SgtPoolId.
*
* Parameters: 'buf' : Pointer to memory buffer with packet
* 'inOffset' : Offset in bytes to start of ESP header
* 'length' : Number of bytes to encrypt
* 'outOffset' : Offset in bytes to where SEC4 will store the decrypted data
* 'sec4IpsecSa' : IPsec SA
* 'saIndex' : The frame queue index to use
*
* Returns: E_OK if ok, otherwise error code
*
*/
int sec4_ipsec_inbound_request(uint8_t *buf, uint16_t inOffset, uint16_t length, uint16_t outOffset,
t_sec4IpsecSa *sec4IpsecSa, uint16_t saIndex, uint8_t poolId)
{
physAddress_t p_phys;
t_sec4IpsecSgTbl *sgTbl;
uint32_t fqIx = (uint32_t) saIndex; /* Frame queue index */
uint8_t *p = (uint8_t *)((uint32_t)buf + inOffset);
int status;
SEC4Dump(DBGTXT_SETRQ, ("sec4_ipsec_inbound_request() : buf=0x%x, inOffset=%d, p=0x%x, length=%d, outOffset=%d, sec4IpsecSa=0x%x, saIndex=0x%x\n", buf, inOffset, p, length, outOffset, sec4IpsecSa, saIndex));
/* Prepare Scatter/Gather Table
* SEC4 require a 2 entry SG table in a compund frame to be able to modify a single buffer
* QMAN will create a Sequence descriptor from this info and the FQ pre-header and shared descriptor*/
sgTbl = sec4_buf_alloc(sec4SgtPoolId);
if(sgTbl == NULL)
{
SEC4Dump(DBGTXT_ERROR,("sec4_ipsec_inbound_request() :: Error: No buffer for SG table in pool=0x%x\n", sec4SgtPoolId));
return ERROR_CODE(E_NO_MEMORY);
}
p_phys = XX_VirtToPhys((void *)((uint32_t)buf));
sgTbl->in.qportalAddrHi = (UINT8) (((UINT64)((UINT64) (p_phys)) >> 32) & 0xFFFFFFFF);
sgTbl->in.qportalAddrLo = (UINT32) ((UINT64)((UINT64) (p_phys)) & 0xFFFFFFFF);
sgTbl->in.qportalBpid = (UINT16) poolId;
sgTbl->in.qportalLength = (UINT32) ((length & SEC4_SGT_LENGTH_MASK) | QPORTAL_SGLIST_FINAL); /* The "in" entry is always the final entry of the SG table */
sgTbl->in.qportalOffset = (UINT16) (inOffset & SEC4_SGT_OFFSET_MASK);
sgTbl->out.qportalAddrHi = sgTbl->in.qportalAddrHi;
sgTbl->out.qportalAddrLo = sgTbl->in.qportalAddrLo;
sgTbl->out.qportalBpid = (UINT16) poolId;
sgTbl->out.qportalLength = (UINT32) ((length - SEC4_IPSEC_ESP_HEADER_SZ) & SEC4_SGT_LENGTH_MASK);
sgTbl->out.qportalOffset = (UINT16) (outOffset & SEC4_SGT_OFFSET_MASK);
switch(sec4IpsecSa->cryptoAlg)
{
case e_IPSEC_CRYPTO_ALG_3DES:
sgTbl->out.qportalLength -= SEC4_IPSEC_ESP_DES_IV_SZ;
break;
case e_IPSEC_CRYPTO_ALG_AES_CBC:
sgTbl->out.qportalLength -= SEC4_IPSEC_ESP_AES_IV_SZ;
break;
default:
/* Unsupported alg */
return ERROR_CODE(E_INVALID_ID);
}
SEC4Dump(DBGTXT_SVCRQ,("sgTbl->out.qportalAddrHi=0x%x, sgTbl->out.qportalAddrLo=0x%x, sgTbl->out.qportalBpid=%d, sgTbl->out.qportalLength=0x%x, sgTbl->out.qportalOffset=%d\n",\
sgTbl->out.qportalAddrHi, sgTbl->out.qportalAddrLo, sgTbl->out.qportalBpid, sgTbl->out.qportalLength, sgTbl->out.qportalOffset));
SEC4Dump(DBGTXT_SVCRQ,("sgTbl->in.qportalAddrHi=0x%x, sgTbl->in.qportalAddrLo=0x%x, sgTbl->in.qportalBpid=%d, sgTbl->in.qportalLength=0x%x, sgTbl->in.qportalOffset=%d\n",\
sgTbl->in.qportalAddrHi, sgTbl->in.qportalAddrLo, sgTbl->in.qportalBpid, sgTbl->in.qportalLength, sgTbl->in.qportalOffset));
/* Enqueue on queue Interface */
if(status = sec4_qi_enqueue(sgTbl, sec4QmanEnqueueFqidBase + fqIx) != E_OK)
{
SEC4Dump(DBGTXT_ERROR,("sec4_ipsec_inbound_request() :: qportalEnqueue returned error. fqId=0x%x\n", sec4QmanEnqueueFqidBase + fqIx));
return status;
}
SEC4Dump(DBGTXT_SVCRQ,("sec4_ipsec_inbound_request() :: p=0x%x enqueued on fqId=0x%x\n", p, sec4QmanEnqueueFqidBase + fqIx));
return E_OK;
}
/* Debug functions */
#ifdef DEBUG
int sec4_print_fq_map(void)
{
int i,j;
char buf[128];
int ix=0;
bool found=FALSE;
int noofSa=0;
t_sec4IpsecSa *sec4IpsecSaCache = (t_sec4IpsecSa *)h_sec4IpsecSaCache;
ix = sprintf(buf,"SA-> Frame queue core map @0x%x:\0", sec4IpsecSaFqMap);
XX_Print("%s\n",buf);
ix = 0;
for(i=0; i < sec4IpsecSaCacheNoofEntries; i++)
{
ix += sprintf(buf+ix,"%d\t(0x%08x) ", i, sec4IpsecSaCache[i].spi);
for(j=0; j<7; j++)
{
if(sec4IpsecSaFqMap[i][j] != 0)
{
ix += sprintf(buf+ix,"core%d:0x%x ", j, sec4IpsecSaFqMap[i][j]);
found = TRUE;
}
}
ix += sprintf(buf+ix, "\0");
if(found)
{
noofSa++;
XX_Print("%s\n",buf);
}
ix = 0;
found = FALSE;
}
XX_Print("No of populated SA = %d\n", noofSa);
return 0;
}
int sec4_print_sa_cache(void)
{
int i,j;
char buf[128];
int ix=0;
bool found=FALSE;
int noofSa=0;
t_sec4IpsecSa *sec4IpsecSaCache = (t_sec4IpsecSa *)h_sec4IpsecSaCache;
ix = sprintf(buf,"SEC4 SA cache @0x%x for %d entries:", (uint32_t)sec4IpsecSaCache, sec4IpsecSaCacheNoofEntries);
XX_Print("%s\n",buf);
ix = 0;
for(i=0; i < sec4IpsecSaCacheNoofEntries; i++)
{
ix += sprintf(buf+ix,"%d\t ", i);
if(sec4IpsecSaCache[i].h_ShrJobDesc != NULL)
{
ix += sprintf(buf+ix," spi=0x%x, h_ShrJobDesc=0x%x\0", sec4IpsecSaCache[i].spi, sec4IpsecSaCache[i].h_ShrJobDesc);
found = TRUE;
}
if(found)
{
noofSa++;
XX_Print("%s\n",buf);
}
ix = 0;
found = FALSE;
}
XX_Print("No of populated SA = %d\n", noofSa);
return 0;
}
#endif /* #ifdef DEBUG */
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* SEC4_qportal_set
*===========================================================================
* Description: Set what queue portal to use to interact with QMAN.
* This needs to be called before issuing any jobs to the SEC4.
*
* Parameters: 'qportal' : pointer to a queue portal
* Returns:
*
*/
void SEC4_qportal_set(void *qportal)
{
sec4Qportal = (QPORTAL *) qportal;
SEC4Dump(DBGTXT_INITDEV, ("SEC4 : Qportal set : sec4Qportal=0x%x\n", sec4Qportal));
}
/*
*===========================================================================
* SEC4_bportal_set
*===========================================================================
* Description: Set what buffer portal to use to interact with BMAN to get
* and release buffers.
* This needs to be called before issuing any jobs to the SEC4.
*
* Parameters: 'bportal' : pointer to a buffer portal
* 'poolId' : Pool ID for memory pool to allocale SEC4 internal buffers from
* Returns:
*
*/
void SEC4_bportal_set(void *bportal, uint32_t poolId)
{
sec4Bportal = (BPORTAL *) bportal;
sec4SgtPoolId = (uint8_t) poolId;
SEC4Dump(DBGTXT_INITDEV, ("SEC4 : Bportal set : sec4Bportal=0x%x poolId=%d\n", sec4Bportal, poolId));
}
/*
*===========================================================================
* SEC4_qman_enqueue_fqix_base_set
*===========================================================================
* Description: Set the base frame queue index to use for IPsec SA frame queues.
* The SEC4 need an unique frame queue for each SA.
* This needs to be called before issuing any jobs to the SEC4.
*
* Parameters: 'ixBase' : Base frame queue ID to use for IPsec SA jobs to the
* SEC4 engine
* Returns:
*
*/
void SEC4_qman_enqueue_fqix_base_set(uint32_t ixBase)
{
sec4QmanEnqueueFqidBase = ixBase;
SEC4Dump(DBGTXT_INITDEV, ("SEC4 : QMAN enqueue frame queue base set : sec4QmanEnqueueFqidBase=0x%x\n", sec4QmanEnqueueFqidBase));
}
/*
*===========================================================================
* SEC4_qman_dequeue_fqix_set
*===========================================================================
* Description: Set the base frame queue index for completed IPsec jobs from
* the SEC4 engine.
* The SEC4 will use this index for completed outbound(encrypt) jobs.
* And this index+1 for completed inbound(decrypt) jobs.
* This needs to be called before issuing any jobs to the SEC4.
*
* Parameters: 'ixBaseEncrypt' : Base frame queue ID to use for completed encrypt IPsec SA jobs from the SEC4 engine.
* 'ixBaseDecrypt' : Base frame queue ID to use for completed decrypt IPsec SA jobs from the SEC4 engine.
* Returns:
*
*/
void SEC4_qman_dequeue_fqix_set(uint32_t ixBaseEncrypt, uint32_t ixBaseDecrypt)
{
sec4QmanDequeueEncryptFqidBase = ixBaseEncrypt;
sec4QmanDequeueDecryptFqidBase = ixBaseDecrypt;
SEC4Dump(DBGTXT_INITDEV, ("SEC4 : QMAN dequeue frame queue bases set :"\
" sec4QmanDequeueEncryptFqidBase=0x%x"\
" sec4QmanDequeueDecryptFqidBase=0x%x\n",\
sec4QmanDequeueEncryptFqidBase,\
sec4QmanDequeueDecryptFqidBase));
}
/*
*===========================================================================
* SEC4_ipsec_set_sa_cache_size
*===========================================================================
* Description: Set the number of entries for the IPsec SA cache
*
* Parameters: 'noofEntries' : number of entries for the IPsec SA cache
*
* Returns:
*
*/
void SEC4_ipsec_set_sa_cache_size(uint32_t noofEntries)
{
sec4IpsecSaCacheNoofEntries = noofEntries;
SEC4Dump(DBGTXT_INITDEV, ("SEC4 : IPsec SA cache size set to %d entries\n", noofEntries));
}
/*
*===========================================================================
* SEC4_ipsec_set_shm
*===========================================================================
* Description: Set the base address of the IPsec shared memory
*
* Parameters: 'p' : base address of the IPsec shared memory
*
* Returns:
*
*/
void SEC4_ipsec_set_shm(void *p, uint32_t size)
{
h_sec4Shm = (t_Handle) p;
SEC4Dump(DBGTXT_INITDEV, ("SEC4 : IPsec shared memory base set at 0x%x for %d bytes\n",\
h_sec4Shm, size));
}
/*
*===========================================================================
* SEC4_populate_sa
*===========================================================================
* Description: Creates a shared descriptor to be used by SEC4 engine for IPsec
* jobs. This needs to be called for each SA before submitting any
* IPsec jobs for an SA
*
* Parameters: 'sa' : Ipcom SA structure
* 'sa_index' : The index for this SA. This will map to what frame
* queue to use to the SEC4 engine.
* 'enc' : 1 for outbound(encrypt) SA, 0 for inbound(decrypt) SA
* Returns: SEC4_SUCCESS if ok, otherwise error code
*
*/
int SEC4_populate_sa(uint32_t spi, uint8_t ipsecVer, uint8_t proto,
e_IpsecAuthenAlg authAlg, e_IpsecCryptoAlg cryptoAlg,
uint8_t *authKey, uint8_t authKeySize, uint8_t *cryptoKey,
uint8_t cryptoKeySize, uint8_t *iv, uint16_t sa_index, int enc)
{
t_Handle h_shrDesc;
t_sec4IpsecSa sec4IpsecSa;
uint32_t fqIx = (uint32_t) sa_index; /* Frame queue index */
t_sec4IpsecSa *sec4IpsecSaCache = (t_sec4IpsecSa *)h_sec4IpsecSaCache;
bool isShDescMatch = FALSE;
int status;
int coreIx;
SANITY_CHECK_EXIT(sec4IpsecSaCache,E_NULL_POINTER);
/* Prepare SEC4 SA */
sec4IpsecSa.ipsecMode = e_IPSEC_MODE_TUNNEL;
sec4IpsecSa.antiReplaySize = e_IPSEC_ARS_0; /* Don't do anti replay checking in SEC4 */
sec4IpsecSa.spi = spi;
sec4IpsecSa.ipsecVer = ipsecVer;
sec4IpsecSa.proto = proto;
sec4IpsecSa.authKey.p_Data = authKey;
sec4IpsecSa.authKey.size = authKeySize;
sec4IpsecSa.authKey.imm = FALSE;
sec4IpsecSa.cryptoKey.p_Data = cryptoKey;
sec4IpsecSa.cryptoKey.size = cryptoKeySize;
sec4IpsecSa.cryptoKey.imm = TRUE;
sec4IpsecSa.authAlg = authAlg;
sec4IpsecSa.cryptoAlg = cryptoAlg;
sec4IpsecSa.iv = iv;
/* Apply lock while updating shared SA cache and associated objects */
sec4spinLockLock(SEC4_SA_CACHE_SPINLOCK_ID);
/* Check if there is an existing entry in the cache */
if(sec4IpsecSaCache[sa_index].h_ShrJobDesc != NULL)
{
/* Is there already a matching entry? */ /* TODO */
if((sec4IpsecSa.spi == sec4IpsecSaCache[sa_index].spi) &&
(sec4IpsecSa.ipsecVer == sec4IpsecSaCache[sa_index].ipsecVer) &&
(sec4IpsecSa.proto == sec4IpsecSaCache[sa_index].proto) &&
/*(sec4IpsecSa.authKey.p_Data == sec4IpsecSaCache[sa_index].authKey.p_Data) && */ /*TODO: Match key data. Must be in shared memory*/
/*(sec4IpsecSa.cryptoKey.p_Data == sec4IpsecSaCache[sa_index].cryptoKey.p_Data) && */
(sec4IpsecSa.authAlg == sec4IpsecSaCache[sa_index].authAlg) &&
(sec4IpsecSa.cryptoAlg == sec4IpsecSaCache[sa_index].cryptoAlg))
{
isShDescMatch = TRUE;
SEC4Dump(DBGTXT_SETRQ,("SEC4_populate_sa() :: sa_index=0x%x already populated with matching SA data\n", sa_index));
/* Check if the frame queue has been setup for this SA on this core */
if(sec4IpsecSaFqMap[fqIx][sec4CoreId] != NULL)
{
SEC4Dump(DBGTXT_SETRQ,("SEC4_populate_sa() :: frame queue for sa_index=0x%x already setup\n", sa_index));
sec4spinLockUnlock(SEC4_SA_CACHE_SPINLOCK_ID);
return SEC4_SUCCESS;
}
}
else
{
SEC4Dump(DBGTXT_SETRQ,("SEC4_populate_sa() :: sa_index=0x%x already populated. Not matching data. Remove it\n", sa_index));
/* Shut down and remove frame queues for all cores for this SA */
for(coreIx=0; coreIx < SEC4_MAXNOOF_CORES; coreIx++)
{
if(sec4IpsecSaFqMap[fqIx][coreIx] != NULL)
{
SEC4Dump(DBGTXT_SETRQ,("SEC4_populate_sa() :: frame queue for sa_index=0x%x already setup. Remove it\n", sa_index));
if((status = sec4_ipsec_free_fq(sec4IpsecSaFqMap[fqIx][coreIx])) != E_OK)
{
sec4spinLockUnlock(SEC4_SA_CACHE_SPINLOCK_ID);
return status;
}
sec4IpsecSaFqMap[fqIx][coreIx] = NULL;
}
}
/* All frame queues for this SA has been shut down. It is now safe to remove shared descriptor */
(void) sec4_ipsec_delete_shr_desc(&(sec4IpsecSaCache[sa_index]));
}
}
if(isShDescMatch == FALSE)
{
SEC4Dump(DBGTXT_SETRQ,("SEC4_populate_sa() :: Not matched SA cache entry. Create new shared descriptor for sa_index=0x%x\n", sa_index));
/* Populate IPsec SA cache with new entry */
memcpy(&(sec4IpsecSaCache[sa_index]), &sec4IpsecSa, sizeof(t_sec4IpsecSa));
/* Generate SEC4 "split key" for authentication key as required by HW for IPsec protocol operation */
sec4IpsecSaCache[sa_index].splitKeySize = (int) sec4_create_split_key(sec4IpsecSaCache[sa_index].authKey.p_Data, sec4IpsecSaCache[sa_index].splitKey, sec4IpsecSaCache[sa_index].authAlg);
if(sec4IpsecSaCache[sa_index].splitKeySize == 0)
{
/* Error creating split key */
SEC4Dump(DBGTXT_ERROR,("SEC4_populate_sa() :: Could not create shared split key for sa_index=0x%x\n", sa_index));
/* Clear SA cache entry */
memset(&(sec4IpsecSaCache[sa_index]), 0, sizeof(t_sec4IpsecSa));
sec4spinLockUnlock(SEC4_SA_CACHE_SPINLOCK_ID);
return -1; /* TODO: New error No. */
}
/* Create and add new shared descriptor for this SA */
h_shrDesc = sec4_ipsec_create_shr_desc(&(sec4IpsecSaCache[sa_index]), fqIx, enc);
if(h_shrDesc == NULL)
{
/* Could not create shared descriptor for this SA */
SEC4Dump(DBGTXT_ERROR,("SEC4_populate_sa() :: Could not create shared descriptor for sa_index=0x%x\n", sa_index));
/* Clear SA cache entry */
memset(&(sec4IpsecSaCache[sa_index]), 0, sizeof(t_sec4IpsecSa));
sec4spinLockUnlock(SEC4_SA_CACHE_SPINLOCK_ID);
return -1; /* TODO: New error No. */
}
sec4IpsecSaCache[sa_index].h_ShrJobDesc = h_shrDesc;
}
/* Assign frame queue to be used by this core */
if(sec4_ipsec_assign_fq(sec4IpsecSaCache[sa_index].h_ShrJobDesc, fqIx, enc) != E_OK)
{
SEC4Dump(DBGTXT_ERROR,("SEC4_populate_sa() :: Could not assign frame queue for sa_index=0x%x\n", sa_index));
/* Clear SA cache entry */
memset(&(sec4IpsecSaCache[sa_index]), 0, sizeof(t_sec4IpsecSa));
sec4spinLockUnlock(SEC4_SA_CACHE_SPINLOCK_ID);
return -1; /* TODO: New error No. */
}
SEC4Dump(DBGTXT_SETRQ,("SEC4_populate_sa() :: Frame queue 0x%x assigned using shared descriptor 0x%x for sa_index=0x%x\n", \
sec4IpsecSaFqMap[fqIx][sec4CoreId], sec4IpsecSaCache[sa_index].h_ShrJobDesc, sa_index));
SEC4Dump(DBGTXT_SETRQ,("SEC4_populate_sa() :: sa_index=0x%x populated OK\n", sa_index));
sec4spinLockUnlock(SEC4_SA_CACHE_SPINLOCK_ID);
return SEC4_SUCCESS;
}
/*
*===========================================================================
* SEC4_ipsec_esp_encrypt
*===========================================================================
* Description: Submit a job for IPsec, ESP encrypt to the SEC4 engine
*
* Parameters: 'saIndex' : The index for this SA.
* 'buf' : packet memory buffer
* 'inOffset' : offset to first byte to encrypt
* 'pktlen' : Length of packet
* 'outOffset': This is where SEC4 will put the encrypted output
* 'poolId' : Memory buffer pool for packet
* Returns: SEC4_SUCCESS if ok, otherwise error code
*
*/
int SEC4_ipsec_esp_encrypt(uint16_t saIndex,
uint8_t *buf,
uint16_t inOffset,
uint16_t pktlen,
uint16_t outOffset,
uint8_t poolId)
{
t_sec4IpsecSa *sec4IpsecSa;
int status;
t_sec4IpsecSa *sec4IpsecSaCache = (t_sec4IpsecSa *)h_sec4IpsecSaCache;
/* Get the SEC4 SA from SEC4 SA cache*/
sec4IpsecSa = &(sec4IpsecSaCache[saIndex]);
/* Sanity check of SA */
ASSERT_COND(sec4IpsecSa->h_ShrJobDesc != NULL);
status = sec4_ipsec_outbound_request(buf, inOffset, pktlen, outOffset, sec4IpsecSa, saIndex, poolId);
if(status == E_OK)
return SEC4_SUCCESS;
else
{
SEC4Dump(DBGTXT_ERROR,("SEC4_ipsec_esp_encrypt:: sec4_ipsec_outbound_request failed with error=0x%x\n", status));
return status;
}
}
/*
*===========================================================================
* SEC4_ipsec_esp_decrypt
*===========================================================================
* Description: Submit a job for IPsec, ESP decrypt to the SEC4 engine
*
* Parameters: 'saIndex' : The index for this SA.
* 'buf' : packet memory buffer
* 'inOffset' : offset to first byte to decrypt
* 'pktlen' : Length of packet
* 'outOffset': This is where SEC4 will put the decrypted output
* 'poolId' : Memory pool ID for packet
* Returns: SEC4_SUCCESS if ok, otherwise error code
*
*/
int SEC4_ipsec_esp_decrypt(uint16_t saIndex,
uint8_t *buf,
uint16_t inOffset,
uint16_t pktlen,
uint16_t outOffset,
uint8_t poolId)
{
t_sec4IpsecSa *sec4IpsecSa;
int status;
t_sec4IpsecSa *sec4IpsecSaCache = (t_sec4IpsecSa *)h_sec4IpsecSaCache;
/* Get the SEC4 SA from SEC4 SA cache*/
sec4IpsecSa = &(sec4IpsecSaCache[saIndex]);
/* Sanity check of SA */
ASSERT_COND(sec4IpsecSa->h_ShrJobDesc != NULL);
status = sec4_ipsec_inbound_request(buf, inOffset, pktlen, outOffset, sec4IpsecSa, saIndex, poolId);
if(status == E_OK)
return SEC4_SUCCESS;
else
{
SEC4Dump(DBGTXT_ERROR,("SEC4_ipsec_esp_decrypt:: sec4_ipsec_outbound_request failed with error=0x%x\n", status));
return status;
}
}
#else
int sec4_qi_request_empty_file;
#endif /* #ifdef SEC4_USE_QI */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/