/* ****************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include #include <../src/hwif/h/resource/vxbQorIQQmanPortal.h> #include <../src/hwif/h/resource/vxbQorIQBmanPortal.h> #include #include #include #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 **************************************************************************** */