/************************************************************** * FILE PURPOSE : NETAPI SECURITY CONFIGURATION- * user space access to security transport resources on SOC ************************************************************** * @file netapi_sec.c * * @brief DESCRIPTION: netapi security cfg file for user space transport * library * * REVISION HISTORY: rev 0.0.1 * * Copyright (c) Texas Instruments Incorporated 2010-2011 * * 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. *****************************************************************************/ #include "netapi.h" #include "netapi_loc.h" //add a RX Security Association NETCP_CFG_SA_T netapi_secAddSA(NETAPI_T h, //the netapi handle int iface_no, //inteface to attach to NETAPI_SEC_SA_INFO_T *sa_info ,//info on the SA nwalSecKeyParams_t * key_params, //keys,etc int inflow_mode, //SA implementation mode: inflow or sideband or both NETCP_CFG_ROUTE_HANDLE_T route, //Optional route void **p_data_mode_handle, void **p_inflow_mode_handle, int * perr) { NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h; nwal_RetValue retValue; NetapiNwalTransInfo_t *pTransInfo; nwal_TransID_t trans_id; unsigned int appId = NETAPI_NETCP_MATCH_IPSEC | iface_no; int tunnelId; nwalSaIpSecId_t saInfo; nwalCreateSAParams_t createParam = { /* mac handle */ NULL, //to be filled in 4, /*nwalSaIpSecParam_t */ { 0,/* validParams */ nwal_SA_MODE_TUNNEL, //update from input 64,/* replayWindow */ NWAL_SA_DIR_INBOUND, 0, 0, NWAL_SA_AALG_HMAC_SHA1, //update NWAL_SA_EALG_AES_CTR, //update { 0x00}, /* remMacAddr: NA */ 12, /* macSize */ NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE, /* Continue parsing to next route for match */ NWAL_NEXT_ROUTE_FAIL_ACTION_HOST, /* For next route fail action by default is route to host */ CPPI_PARAM_NOT_SPECIFIED, /* Use default flow configured to NWAL if packet is routed to host */ QMSS_PARAM_NOT_SPECIFIED /* Use default queue configured to NWAL if packet is routed to host */ }, /* nwalSaIpSecKeyParams_t */ {0} }; void * mac_handle = netcp_cfgp_get_mac_handle(&netapi_get_global()->nwal_context,iface_no); *perr =0; if ((!n) || (!sa_info) || (!mac_handle)|| (!p_data_mode_handle) ) {*perr = NETAPI_ERR_BAD_INPUT; return -1;} //reserve a slot tunnelId = netcp_cfgp_find_sa_slot(&netapi_get_global()->nwal_context, iface_no); if (tunnelId <0) {*perr= NETAPI_ERR_NOMEM; return -1; } appId |= (tunnelId<<8); *p_data_mode_handle= NULL; *p_inflow_mode_handle= NULL; if (inflow_mode & NETAPI_SEC_SA_INFLOW) { pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id); if (!pTransInfo) { *perr = NETAPI_ERR_BUSY;netcp_cfgp_delete_sa(&netapi_get_global()->nwal_context,tunnelId); return -1;} pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA; pTransInfo->netapi_handle = h; /* build SA parameters */ saInfo.spi = sa_info->spi; memcpy(&saInfo.dst, &sa_info->dst, sizeof( nwalIpAddr_t)); memcpy(&saInfo.src, &sa_info->src, sizeof( nwalIpAddr_t)); saInfo.proto = sa_info->proto; createParam.macHandle = mac_handle; createParam.ipType = sa_info->ipType; //memcpy(&createParam.saIpSecParam.src,&sa_info->src, sizeof(nwalIpAddr_t)); createParam.saIpSecParam.dir = sa_info->dir; createParam.saIpSecParam.saMode = sa_info->saMode; createParam.saIpSecParam.replayWindow = sa_info->replayWindow; createParam.saIpSecParam.authMode = sa_info->authMode; createParam.saIpSecParam.cipherMode = sa_info->cipherMode; createParam.saIpSecParam.esnLo = sa_info->esnLo; createParam.saIpSecParam.esnHi = sa_info->esnHi; memcpy(&createParam.keyParam,key_params,sizeof(nwalSecKeyParams_t)); if (route != NULL) { netcp_cfgp_build_route(route,&createParam.saIpSecParam.appRxPktFlowId, &createParam.saIpSecParam.appRxPktQueue); } //fire off config message pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING; retValue = nwal_setSecAssoc (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, trans_id, appId, &saInfo, &createParam, &pTransInfo->handle); if(retValue != nwal_OK) { *perr = NETAPI_ERR_NWAL_ERR0; printf (">netapi_sec - ERROR: nwal_setSecAssoc returned Error Code %d\n", retValue); pTransInfo->inUse = nwal_FALSE; netcp_cfgp_delete_sa(&netapi_get_global()->nwal_context,tunnelId); return -1; } //pTransInfo->inUse = nwal_FALSE; //wait here until its done since scheduler isn't running yet most likely.. // todo: make this handled by scheduler poll later ?? if(trans_id != NWAL_TRANSID_SPIN_WAIT) { n->nwal_local.numPendingCfg++; while ((volatile) n->nwal_local.numPendingCfg) { // if response is there, then this poll squirts out in the CTl poll callback, // which handles the rest (including decrmenting #pending!! nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL); } } printf (">netapi sec: SA %d added to mac %d\n", tunnelId, iface_no); pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE; *p_inflow_mode_handle=pTransInfo->handle; pTransInfo->inUse = nwal_FALSE; } //sideband mode if (inflow_mode &NETAPI_SEC_SA_SIDEBAND) { nwalCreateDmSAParams_t dmSaParam; void * dm_handle; memset(&dmSaParam,0,sizeof(nwalCreateDmSAParams_t)); dmSaParam.dmSaParam.dmChnType= (sa_info->dir==NWAL_SA_DIR_INBOUND)? NWAL_DM_CHAN_DECRYPT: NWAL_DM_CHAN_ENCRYPT; /**direction*/ dmSaParam.dmSaParam.replayWindow=sa_info->replayWindow; /**< Replay Window Size */ dmSaParam.dmSaParam.authMode=sa_info->authMode; /**< Authentication Algorithm */ dmSaParam.dmSaParam.cipherMode=sa_info->cipherMode ; /**< Encryption Algorithm */ dmSaParam.dmSaParam.macSize=12; /**todo: pass in or deduce */ dmSaParam.dmSaParam.aadSize=0; /**todo: pass in or deduce */ dmSaParam.dmSaParam.enc1st = (sa_info->dir ==NWAL_SA_DIR_OUTBOUND) ? nwal_TRUE : nwal_FALSE; //encypt 1st for outbound //todo; allow app q for Sideband return dmSaParam.dmSaParam.appRxPktFlowId= CPPI_PARAM_NOT_SPECIFIED; dmSaParam.dmSaParam.appRxPktQueue= CPPI_PARAM_NOT_SPECIFIED; memcpy(&dmSaParam.keyParam,key_params,sizeof(nwalSecKeyParams_t)); retValue = nwal_setDMSecAssoc(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, (nwal_AppId)appId, &dmSaParam, &dm_handle); if(retValue != nwal_OK) { *perr = NETAPI_ERR_NWAL_ERR0; printf (">netapi_sec - ERROR: nwal_setDMSecAssoc returned Error Code %d\n", retValue); netcp_cfgp_delete_sa(&netapi_get_global()->nwal_context,tunnelId); return -1; } printf(">netapisec %d Creating sideband mode SA for %d ( mac %d)\n", tunnelId, iface_no); *p_data_mode_handle = dm_handle; } //save stuff netcp_cfgp_insert_sa(&netapi_get_global()->nwal_context, tunnelId, (sa_info->dir == NWAL_SA_DIR_INBOUND) ? TRUE: FALSE, inflow_mode, &saInfo, &createParam, *p_inflow_mode_handle, *p_data_mode_handle); return (appId); } //enable or disable inflow mode void netapi_secInflowMode(int iface, NETCP_CFG_SA_T sa, int on) { /*todo */ /* FUTURE */ printf(">netapi_sec: dynamic switch between inflow and sideband is not functional yet\n"); } //delete the SA //(internal version) static void netapi_secDelSA_internal(NETAPI_T h,int iface_no, NETCP_CFG_SA_T sa_app_id, int flags, int *perr) { NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h; nwal_RetValue retValue; NetapiNwalTransInfo_t *pTransInfo; nwal_TransID_t trans_id; int tunnelId = (sa_app_id >>8) &0xffff; void * handle_inflow; void * handle_sideband; handle_inflow = netcp_cfgp_get_sa_handles(&netapi_get_global()->nwal_context, tunnelId, &handle_sideband); *perr =0; if(handle_inflow) { //get a transaction id pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id); if (!pTransInfo) { *perr = NETAPI_ERR_BUSY; return ;} pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA; pTransInfo->netapi_handle = h; //issue request retValue = nwal_delSecAssoc( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, trans_id, handle_inflow); if(retValue != nwal_OK) { *perr = NETAPI_ERR_NWAL_ERR0; printf (">netapi_sec - ERROR: nwal_delSA returned Error Code %d\n", retValue); pTransInfo->inUse = nwal_FALSE; return ; } //wait here until its done since scheduler isn't running yet most likely.. // todo: make this handled by scheduler poll later ?? if(trans_id != NWAL_TRANSID_SPIN_WAIT) { n->nwal_local.numPendingCfg++; while ((volatile) n->nwal_local.numPendingCfg) { // if response is there, then this poll squirts out in the CTl poll callback, // which handles the rest (including decrmenting #pending!! nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL); } } printf (">netapi sec: inflow tunnel %d (iface %d) deleted\n",tunnelId,iface_no); pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE; pTransInfo->inUse = nwal_FALSE; } if (handle_sideband) { retValue=nwal_delDMSecAssoc( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, handle_sideband); if(retValue != nwal_OK) { *perr = NETAPI_ERR_NWAL_ERR0; printf (">netapi_sec - ERROR: nwal_delDMSA returned Error Code %d\n", retValue); } else printf(">netapi_sec: Sideband SA deleted\n"); } //zap the entry if (!flags) netcp_cfgp_delete_sa(&netapi_get_global()->nwal_context, tunnelId); } //external version void netapi_secDelSA(NETAPI_T h,int iface_no, NETCP_CFG_SA_T sa_app_id, int *perr) { netapi_secDelSA_internal( h, iface_no, sa_app_id, 0x00, perr); } //****************************************** // Add Policy //****************************************** NETCP_CFG_IPSEC_POLICY_T netapi_secAddRxPolicy(NETAPI_T h, //the netapi handle NETCP_CFG_SA_T sa, //tunnel to attach to nwal_IpType ipType, //V4 or V6 nwalIpAddr_t * src_ip_addr, //src (from where) nwalIpAddr_t * dst_ip_addr, //dst (us) nwalIpOpt_t * ip_qualifiers, //other qualifiers NETCP_CFG_ROUTE_HANDLE_T route, //Optional route int * perr) { NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h; nwal_RetValue retValue; NetapiNwalTransInfo_t *pTransInfo; nwal_TransID_t trans_id; unsigned int appId = NETAPI_NETCP_MATCH_IPSEC_POLICY | (sa&0xff); int policyId; int tunnelId= (sa>>8)&0xff; void * blah; int iface_no = sa&0xff; nwalSecPolParams_t createParam = { 0, /* handle */ NWAL_SA_DIR_INBOUND, 4, /* IP Type */ {0}, /* dst */ {0}, /* src */ {0 },/* IP Options */ NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE, /* Continue parsing to next route for match */ NWAL_NEXT_ROUTE_FAIL_ACTION_HOST, /* For next route fail action by default is route to host */ CPPI_PARAM_NOT_SPECIFIED, /* Use default flow configured to NWAL if packet is routed to host */ QMSS_PARAM_NOT_SPECIFIED /* Use default queue configured to NWAL if packet is routed to host */ }; void * sa_handle = NULL; *perr =0; if ((!n) ) {*perr = NETAPI_ERR_BAD_INPUT; return -1;} sa_handle = netcp_cfgp_get_sa_handles(&netapi_get_global()->nwal_context,tunnelId,&blah); if (!sa_handle) {*perr = NETAPI_ERR_BAD_INPUT; return -1;} pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id); if (!pTransInfo) { *perr = NETAPI_ERR_BUSY; return -1;} pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA_POLICY; pTransInfo->netapi_handle = h; createParam.handle = sa_handle; createParam.ipType = ipType; if (dst_ip_addr) memcpy(&createParam.dst, dst_ip_addr, sizeof(nwalIpAddr_t)); if (src_ip_addr) memcpy(&createParam.src, src_ip_addr, sizeof(nwalIpAddr_t)); if (ip_qualifiers) memcpy(&createParam.ipOpt,ip_qualifiers ,sizeof(nwalIpOpt_t)); if (route != NULL) { netcp_cfgp_build_route(route,&createParam.appRxPktFlowId, &createParam.appRxPktQueue); } //reserve a slot policyId = netcp_cfgp_find_policy_slot(&netapi_get_global()->nwal_context, tunnelId); if (policyId <0) {*perr= NETAPI_ERR_NOMEM; return -1; } appId |= (policyId<<8); //fire off config message pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING; retValue = nwal_setSecPolicy (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, trans_id, appId, &createParam, &pTransInfo->handle); if(retValue != nwal_OK) { *perr = NETAPI_ERR_NWAL_ERR0; printf (">netapi sec - ERROR: nwal_setPolicy returned Error Code %d\n", retValue); pTransInfo->inUse = nwal_FALSE; netcp_cfgp_delete_policy(&netapi_get_global()->nwal_context,policyId); return -1; } //pTransInfo->inUse = nwal_FALSE; //wait here until its done since scheduler isn't running yet most likely.. // todo: make this handled by scheduler poll later ?? if(trans_id != NWAL_TRANSID_SPIN_WAIT) { n->nwal_local.numPendingCfg++; while ((volatile) n->nwal_local.numPendingCfg) { // if response is there, then this poll squirts out in the CTl poll callback, // which handles the rest (including decrmenting #pending!! nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL); } } printf (">netapi sec: SA %d added to tunnel %d mac %d\n", policyId, tunnelId, iface_no); //todo: the sideband i/f //save stuff netcp_cfgp_insert_policy(&netapi_get_global()->nwal_context, policyId, (void *) pTransInfo->handle); pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE; pTransInfo->inUse = nwal_FALSE; return (appId); } //************************ //Delete Policy (internal) //*********************** static void netapi_secDelRxPolicy_internal(NETAPI_T h, NETCP_CFG_IPSEC_POLICY_T policy_app_id, int flags, int *perr) { NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h; nwal_RetValue retValue; NetapiNwalTransInfo_t *pTransInfo; nwal_TransID_t trans_id; int policyId = (policy_app_id >>8) &0xffff; void * handle_policy=NULL; handle_policy = netcp_cfgp_get_policy(&netapi_get_global()->nwal_context,policyId); ; if (!handle_policy) {*perr = NETAPI_ERR_BAD_INPUT; return ;} *perr =0; //get a transaction id pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id); if (!pTransInfo) { *perr = NETAPI_ERR_BUSY; return ;} pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA_POLICY; pTransInfo->netapi_handle = h; //issue request retValue = nwal_delSecPolicy( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle, trans_id, handle_policy); if(retValue != nwal_OK) { *perr = NETAPI_ERR_NWAL_ERR0; printf (">netsec - ERROR: nwal_delSAPolicy returned Error Code %d\n", retValue); pTransInfo->inUse = nwal_FALSE; return ; } //wait here until its done since scheduler isn't running yet most likely.. // todo: make this handled by scheduler poll later ?? if(trans_id != NWAL_TRANSID_SPIN_WAIT) { n->nwal_local.numPendingCfg++; while ((volatile) n->nwal_local.numPendingCfg) { // if response is there, then this poll squirts out in the CTl poll callback, // which handles the rest (including decrmenting #pending!! nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL); } } printf (">netapi sec: policy %d (iface %d) deleted\n",policyId,(policy_app_id&0xff)); pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE; pTransInfo->inUse = nwal_FALSE; //zap the entry if (!flags) netcp_cfgp_delete_policy(&netapi_get_global()->nwal_context, policyId); } //************************ //Delete Policy //*********************** void netapi_secDelRxPolicy(NETAPI_T h, NETCP_CFG_IPSEC_POLICY_T policy_app_id, int *perr) { netapi_secDelRxPolicy_internal(h, policy_app_id, 0, perr); }