/* * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* Standard includes */ #include #include #include /* ipsecmgr includes */ #include #include #include "netapilib_interface.h" extern ipsecMgrMcb_t globalDB; extern NETAPI_T netapi_handle; /************************************************************************** * FUNCTION PURPOSE: Internal function to find a free slot to store APPID * in list ************************************************************************** * DESCRIPTION: Internal internal function to find a free slot in SA list for an SA ********************************************************************/ int findFreeAppIdSlot(ipsecMgrAppId_T *pList) { int i; for(i=0;i<64;i++) { if (!pList[i].in_use) { if (free) pList[i].in_use = 1; //pending return i; } } return -1; } /******************************************************************** * FUNCTION PURPOSE: Internal function to find a SA app id in SA list * and free SA Slot entry if specified ******************************************************************** * DESCRIPTION: Internal function to find a SA app id in SA list * and free SA Slot entry if specified ********************************************************************/ int findAppIdSlot(ipsecMgrAppId_T *pList, uint32_t saAppId, int free) { int i; for(i=0;i<64;i++) { if ((pList[i].in_use) && (pList[i].saAppId == saAppId)) { if(free) pList[i].in_use = 0; return i; } } return -1; } /************************************************************************** * FUNCTION PURPOSE: The function is used to translate the SA configuration * parameters received from the IPSec Snopper and call the NETAPI function * to create a security association ********************************************************************/ int netapilib_ifAddSA ( ipsecmgr_af_t af, ipsecmgr_sa_id_t *sa_id, ipsecmgr_sa_info_t *sa_info, ipsecmgr_sa_dscp_map_cfg_t *dscp_map_cfg, ipsecmgr_ifname_t *if_name, ipsecmgr_sa_encap_tmpl_t *encap, ipsecmgr_fp_handle_t *sa_handle ) { uint8_t auth_key[36]; uint8_t encr_key[36]; int error, index,slot; NETAPI_SEC_SA_INFO_T saInfo; nwalSecKeyParams_t keyParams; void * p_rx_inflow_mode_handle; void * p_tx_inflow_mode_handle; NETCP_CFG_ROUTE_T route; NETCP_CFG_FLOW_T flow; NETCP_CFG_SA_HANDLE_T pSaHandle; ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifAddSA:, DEBUG: Translating SA\n"); memset((void *)&saInfo, 0, sizeof (NETAPI_SEC_SA_INFO_T)); memset((void *)&keyParams, 0, sizeof (nwalSecKeyParams_t)); memset((void *)&route, 0, sizeof (NETCP_CFG_ROUTE_T)); memset((void *)&flow, 0, sizeof (NETCP_CFG_FLOW_T)); flow.dma_engine= 1; flow.flowid = globalDB.flowId; route.p_flow = &flow; route.p_dest_q = globalDB.pktio_channel; /* Initialize the SA Config structure. */ /* Get the IP protocol version. */ if (af == IPSECMGR_AF_IPV4) { saInfo.ipType = nwal_IPV4; /* Populate the source and destination IP addresses. */ for (index = 0; index < 4; index++) { saInfo.dst.ipv4[index] = sa_id->daddr.ipv4[index]; saInfo.src.ipv4[index] = sa_info->saddr.ipv4[index]; } } else if (af == IPSECMGR_AF_IPV6) { saInfo.ipType = nwal_IPV6; /* Populate the source and destination IP addresses. */ for (index = 0; index < 16; index++) { saInfo.dst.ipv6[index] = sa_id->daddr.ipv6[index]; saInfo.src.ipv6[index] = sa_info->saddr.ipv6[index]; } } else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA: Address family (%d) is invalid\n", af); return -1; } /* Get the SPI. */ saInfo.spi = sa_id->spi; /* Get the SA direction. */ if (sa_info->dir == DIR_INBOUND) { slot = findFreeAppIdSlot(&globalDB.rx_sa[0]); if (slot == -1) { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA:, Too many INBOUND SAs already offloaded\n"); return -1; } saInfo.dir = NWAL_SA_DIR_INBOUND; } else if (sa_info->dir == DIR_OUTBOUND) { slot = findFreeAppIdSlot(&globalDB.tx_sa[0]); if (slot == -1) { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA:, Too many OUTBOUND SAs already offloaded\n"); return -1; } saInfo.dir = NWAL_SA_DIR_OUTBOUND; } else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA: IPSec direction (%d) is invalid\n", sa_info->dir); return -1; } /* Get the replay Window */ saInfo.replayWindow = sa_info->replay_window; /* Get the IPSec protocol. */ if (sa_id->proto == SA_PROTO_AH) saInfo.proto = nwal_IpSecProtoAH; else if (sa_id->proto == SA_PROTO_ESP) saInfo.proto = nwal_IpSecProtoESP; else { ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO, "netapilib_ifAddSA: IPSec protocol (%d) is invalid.\n", sa_id->proto); return -1; } /* Get the IPSec mode. */ if (sa_info->mode == SA_MODE_TRANSPORT) saInfo.saMode = nwal_SA_MODE_TRANSPORT; else if (sa_info->mode == SA_MODE_TUNNEL) saInfo.saMode = nwal_SA_MODE_TUNNEL; else { ipsecmgr_syslog_msg(SYSLOG_LEVEL_INFO, "netapilib_ifAddSA: IPSec mode (%d) is invalid.\n", sa_info->mode); return -1; } /* Get the authentication mode algorithm. */ if (sa_info->auth.algo == SA_AALG_HMAC_SHA1) saInfo.authMode = NWAL_SA_AALG_HMAC_SHA1; else if (sa_info->auth.algo == SA_AALG_HMAC_MD5) saInfo.authMode = NWAL_SA_AALG_HMAC_MD5; else if (sa_info->auth.algo == SA_AALG_NONE || sa_info->auth.algo == SA_AALG_NULL) saInfo.authMode = NWAL_SA_AALG_NULL; else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifAddSA: Authentication algorithm (%d) is invalid\n", sa_info->auth.algo); return -1; } /* Get the encryption mode algorithm. */ if (sa_info->enc.algo == SA_EALG_NULL) saInfo.cipherMode = NWAL_SA_EALG_NULL; else if (sa_info->enc.algo == SA_EALG_AES_CTR) saInfo.cipherMode = NWAL_SA_EALG_AES_CTR; else if (sa_info->enc.algo == SA_EALG_AES_CBC) saInfo.cipherMode = NWAL_SA_EALG_AES_CBC; else if (sa_info->enc.algo == SA_EALG_3DES_CBC) saInfo.cipherMode = NWAL_SA_EALG_3DES_CBC; else if (sa_info->enc.algo == SA_EALG_DES_CBC) saInfo.cipherMode = NWAL_SA_EALG_DES_CBC; else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA: Encryption algorithm (%d) is invalid\n", sa_info->enc.algo); return -1; } /* Validate the key lengths. */ if ((keyParams.macKeySize = sa_info->auth_key_len) > 32) { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA: Authentication key size (%d) is invalid.\n", sa_info->auth_key_len); return -1; } if ((keyParams.encKeySize = sa_info->enc_key_len) > 32) { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA: Encryption key size (%d) is invalid.\n", sa_info->enc_key_len); return -1; } /* Get the authentication/encryption keys. */ keyParams.pAuthKey = &sa_info->auth_key[0]; keyParams.pEncKey = &sa_info->enc_key[0]; if (saInfo.dir == NWAL_SA_DIR_INBOUND) { /* Inbound == RX */ globalDB.rx_sa[slot].saAppId = netapi_secAddSA(netapi_handle, NETCP_CFG_NO_INTERFACE, &saInfo, &keyParams, NETAPI_SEC_SA_INFLOW, (NETCP_CFG_ROUTE_HANDLE_T)&route, &p_rx_inflow_mode_handle, &p_tx_inflow_mode_handle, NULL, &error); if (error == NETAPI_ERR_OK) { *sa_handle = globalDB.rx_sa[slot].saAppId; } else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA: netapi_secAddSA returned error: %d.\n", error); return -1; } } else { /* OUTBOUND == TX */ globalDB.tx_sa[slot].saAppId = netapi_secAddSA(netapi_handle, NETCP_CFG_NO_INTERFACE, &saInfo, &keyParams, NETAPI_SEC_SA_INFLOW, (NETCP_CFG_ROUTE_HANDLE_T)NULL, &p_rx_inflow_mode_handle, &p_tx_inflow_mode_handle, NULL, &error); if (error == NETAPI_ERR_OK) { *sa_handle = globalDB.tx_sa[slot].saAppId; printf("netapilib_ifAddSA: using slot: %d\n", slot); #if 0 netapi_secGetChanHandles(netapi_handle, saAppIdOut, NULL, &pSaHandle); #endif } else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA: netapi_secAddSA returned error: %d.\n", error); return -1; } } ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifAddSA: Translation of SA successful, app_id: 0x%x\n", *sa_handle); /* SA was created successfully. */ return 0; } /************************************************************************** * FUNCTION PURPOSE: The function is used to translate the SA configuration * parameters received from the IPSec Snopper and call the NETAPI function * to delete a security association ********************************************************************/ int netapilib_ifDeleteSA (ipsecmgr_fp_handle_t sa_handle) { int error, slot; slot = findAppIdSlot(&globalDB.rx_sa[0],sa_handle, 1); /* Determine if rx_sa or tx_sa is being deleted */ if (slot != -1) { /* found rx SA, see if there is policy assoicated with rx SA if so, then delete it first*/ if (globalDB.rx_sa[slot].spAppId) { netapi_secDelRxPolicy(netapi_handle, (NETCP_CFG_IPSEC_POLICY_T) globalDB.rx_sa[slot].spAppId, &error); ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifDeleteSA: SP deleted: sp_app_id: 0x%x, slot: %d, error: %d\n", globalDB.rx_sa[slot].spAppId, slot, error); netapi_secDelSA(netapi_handle, NETCP_CFG_NO_INTERFACE, (NETCP_CFG_SA_T) sa_handle, &error); ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifDeleteSA: SA deleted: sa_app_id: 0x%x, slot: %d, error: %d\n", sa_handle, slot, error); } } else { /* not rx SA, check for tx_sa */ slot = findAppIdSlot(&globalDB.tx_sa[0], sa_handle, 1); if (slot != -1) { /* found tx SA, delete it now */ netapi_secDelSA(netapi_handle, NETCP_CFG_NO_INTERFACE, (NETCP_CFG_SA_T) sa_handle, &error); ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifDeleteSA: SA deleted: sa_app_id: 0x%x, slot: %d, error: %d\n", sa_handle, slot, error); } else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifDeleteSA: sa_app_id 0x%x not found in internal list\n", sa_handle); return -1; } } return error; } /************************************************************************** * FUNCTION PURPOSE: The function is used to translate the SP configuration * parameters received from the IPSec Snopper and call the NETAPI function * to create a security policy ********************************************************************/ int32_t netapilib_ifAddSP ( ipsecmgr_af_t af, ipsecmgr_selector_t *sel, ipsecmgr_dir_t dir, uint32_t reqid, ipsecmgr_fp_handle_t sa_handle, ipsecmgr_policy_id_t policy_id, ipsecmgr_fp_handle_t *sp_handle ) { #ifdef ENABLE_ADD_POLICY NETCP_CFG_IPSEC_POLICY_T spAppIdIn; int error, index, slot; nwal_IpType ipType; nwalIpAddr_t src_ip_addr; nwalIpAddr_t dst_ip_addr; nwalIpOpt_t ip_qualifiers; NETCP_CFG_SA_T sa =(NETCP_CFG_SA_T)sa_handle; NETCP_CFG_ROUTE_T route; NETCP_CFG_FLOW_T flow; NETCP_CFG_PA_HANDLE_T pPaHandleOuterIP; NETCP_CFG_PA_HANDLE_T pPaHandleInnerIP; NETCP_CFG_SA_HANDLE_T pSaHandle; ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,"netapilib_ifAddSP: called\n"); if (dir == DIR_OUTBOUND) { ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifAddSP: called for outbound SA, no RX policy required\n"); return 0; } slot = findAppIdSlot(&globalDB.rx_sa[0],sa_handle, 0); if (slot == -1) { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA:, Too many OUTBOUND SAs already offloaded\n"); return -1; } flow.dma_engine= 1; flow.flowid = globalDB.flowId; route.p_flow = &flow; route.p_dest_q = globalDB.pktio_channel; /* Get the IP protocol version. */ if (af == IPSECMGR_AF_IPV4) { ipType = nwal_IPV4; /* Populate the source and destination IP addresses. */ for (index = 0; index < 4; index++) { dst_ip_addr.ipv4[index] = sel->daddr.ipv4[index]; src_ip_addr.ipv4[index] = sel->saddr.ipv4[index]; } } else if (af == IPSECMGR_AF_IPV6) { ipType = nwal_IPV6; /* Populate the source and destination IP addresses. */ for (index = 0; index < 16; index++) { dst_ip_addr.ipv6[index] = sel->daddr.ipv6[index]; src_ip_addr.ipv6[index] = sel->saddr.ipv6[index]; } } else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSP: Address family (%d) is invalid\n", af); return -1; } globalDB.rx_sa[slot].spAppId = netapi_secAddRxPolicy(netapi_handle, (NETCP_CFG_SA_T) sa_handle, ipType, &src_ip_addr, &dst_ip_addr, NULL, (NETCP_CFG_ROUTE_HANDLE_T)&route, NULL, &error); if (error == NETAPI_ERR_OK) { *sp_handle = globalDB.rx_sa[slot].spAppId; } else { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifAddSA: netapi_secAddRxPolicy returned error: %d.\n", error); return -1; } ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifAddSA: Translation of SP successful, app_id: 0x%x\n", *sp_handle); #if 0 netapi_secGetChanHandles(netapi_handle, (NETCP_CFG_SA_T)sa_handle, globalDB.rx_sa[slot].spAppId, &pPaHandleOuterIP, &pPaHandleInnerIP, &pSaHandle); #endif #endif return 0; } /************************************************************************** * FUNCTION PURPOSE: The function is used to translate the SP configuration * parameters received from the IPSec Snopper and call the NETAPI function * to delete a security association ********************************************************************/ int32_t netapilib_ifDeleteSP ( ipsecmgr_fp_handle_t sp_handle, ipsecmgr_policy_id_t policy_id, ipsecmgr_dir_t dir ) { /* Security Policy is deleted as part of deleting SA */ return 0; #if 0 int error =0; ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,"netapilib_ifDeleteSP: called\n"); if (dir == DIR_OUTBOUND) { ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifDeleteSP: called for outbound SA, no RX policy to delete\n"); return 0; } netapi_secDelRxPolicy(netapi_handle, (NETCP_CFG_IPSEC_POLICY_T) sp_handle, &error); return 0; #endif } /************************************************************************** * FUNCTION PURPOSE: The function is used to translate the SA configuration * parameters received from the IPSec Snopper and retrieve SA context * information for SA. *************************************************************************/ int netapilib_ifGetSACtx ( ipsecmgr_fp_handle_t sa_handle, ipsecmgr_sa_hw_ctx_t* hw_ctx ) { uint32_t swInfo0 = 0; uint32_t swInfo1 = 0; nwalGlobCxtInfo_t info; nwal_RetValue retVal; memset(&info, 0, sizeof(nwalGlobCxtInfo_t)); NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) netapi_handle; ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO,"netapilib_ifGetSACtx: called\n"); netapip_netcpCfgGetSaInflowInfo(&netapi_get_global()->nwal_context, (NETCP_CFG_SA_T) sa_handle, &swInfo0, &swInfo1); hw_ctx->swinfo_sz = 2; hw_ctx->swinfo[0] = swInfo0; hw_ctx->swinfo[1] = swInfo1; retVal = nwal_getGlobCxtInfo(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, &info); if (retVal != nwal_OK) { ipsecmgr_syslog_msg (SYSLOG_LEVEL_ERROR, "netapilib_ifGetSACtx: nwal_getGlobCxtInfo returned error: 0x%x\n", retVal); return -1; } hw_ctx->flow_id = info.rxSaPaFlowId; ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifGetSACtx: rxPaSaFlowId: 0x%x, rxSaPaFlowId: 0x%x\n", info.rxPaSaFlowId, info.rxSaPaFlowId); ipsecmgr_syslog_msg (SYSLOG_LEVEL_INFO, "netapilib_ifGetSACtx: swInfo0: 0x%x, swInfo1: 0x%x, flowId: 0x%x\n", hw_ctx->swinfo[0], hw_ctx->swinfo[1], hw_ctx->flow_id); /* return success */ return 0; }