1 /**************************************************************
2 * FILE PURPOSE : NETAPI SECURITY CONFIGURATION-
3 * user space access to security transport resources on SOC
4 **************************************************************
5 * @file netapi_sec.c
6 *
7 * @brief DESCRIPTION: netapi security cfg file for user space transport
8 * library
9 *
10 * REVISION HISTORY: rev 0.0.1
11 *
12 * Copyright (c) Texas Instruments Incorporated 2010-2011
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the
24 * distribution.
25 *
26 * Neither the name of Texas Instruments Incorporated nor the names of
27 * its contributors may be used to endorse or promote products derived
28 * from this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *****************************************************************************/
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include "netapi.h"
47 #include "netapi_loc.h"
50 //add a RX Security Association
51 NETCP_CFG_SA_T netapi_secAddSA(NETAPI_T h, //the netapi handle
52 int iface_no, //inteface to attach to
53 NETAPI_SEC_SA_INFO_T *sa_info ,//info on the SA
54 nwalSecKeyParams_t * key_params, //keys,etc
55 int inflow_mode, //SA implementation mode: inflow or sideband or both
56 NETCP_CFG_ROUTE_HANDLE_T route, //Optional route
57 void **p_data_mode_handle,
58 void **p_inflow_mode_handle,
59 int * perr)
60 {
61 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
62 nwal_RetValue retValue;
63 NetapiNwalTransInfo_t *pTransInfo;
64 nwal_TransID_t trans_id;
65 unsigned int appId = NETAPI_NETCP_MATCH_IPSEC | iface_no;
66 int tunnelId;
67 nwalSaIpSecId_t saInfo;
68 int have_to_wait=1;
69 nwalCreateSAParams_t createParam =
70 {
71 /* mac handle */
72 NULL, //to be filled in
73 4,
75 /*nwalSaIpSecParam_t */
76 {
77 0,/* validParams */
78 nwal_SA_MODE_TUNNEL, //update from input
79 64,/* replayWindow */
80 NWAL_SA_DIR_INBOUND,
81 0,
82 0,
83 NWAL_SA_AALG_HMAC_SHA1, //update
84 NWAL_SA_EALG_AES_CTR, //update
85 { 0x00}, /* remMacAddr: NA */
86 12, /* macSize */
87 NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE, /* Continue parsing to next route for match */
88 NWAL_NEXT_ROUTE_FAIL_ACTION_HOST, /* For next route fail action by default is route to host */
89 CPPI_PARAM_NOT_SPECIFIED, /* Use default flow configured to NWAL if packet is routed to host */
90 QMSS_PARAM_NOT_SPECIFIED /* Use default queue configured to NWAL if packet is routed to host */
91 },
92 /* nwalSaIpSecKeyParams_t */
93 {0}
94 };
95 void * mac_handle = netcp_cfgp_get_mac_handle(&netapi_get_global()->nwal_context,iface_no);
97 *perr =0;
98 if ((!n) || (!sa_info) || (!p_data_mode_handle) ) {*perr = NETAPI_ERR_BAD_INPUT; return -1;}
100 //reserve a slot
101 tunnelId = netcp_cfgp_find_sa_slot(&netapi_get_global()->nwal_context,
102 iface_no);
103 if (tunnelId <0) {*perr= NETAPI_ERR_NOMEM; return -1; }
104 appId |= (tunnelId<<8);
106 *p_data_mode_handle= NULL;
107 *p_inflow_mode_handle= NULL;
109 if (inflow_mode & NETAPI_SEC_SA_INFLOW)
110 {
112 pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);
113 if (!pTransInfo) { *perr = NETAPI_ERR_BUSY;netcp_cfgp_delete_sa(&netapi_get_global()->nwal_context,tunnelId); return -1;}
114 pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA;
115 pTransInfo->netapi_handle = h;
117 /* build SA parameters */
118 saInfo.spi = sa_info->spi;
119 memcpy(&saInfo.dst, &sa_info->dst, sizeof( nwalIpAddr_t));
120 memcpy(&saInfo.src, &sa_info->src, sizeof( nwalIpAddr_t));
121 saInfo.proto = sa_info->proto;
122 createParam.macHandle = mac_handle;
123 createParam.ipType = sa_info->ipType;
124 //memcpy(&createParam.saIpSecParam.src,&sa_info->src, sizeof(nwalIpAddr_t));
125 createParam.saIpSecParam.dir = sa_info->dir;
126 createParam.saIpSecParam.saMode = sa_info->saMode;
127 createParam.saIpSecParam.replayWindow = sa_info->replayWindow;
128 createParam.saIpSecParam.authMode = sa_info->authMode;
129 createParam.saIpSecParam.cipherMode = sa_info->cipherMode;
130 createParam.saIpSecParam.esnLo = sa_info->esnLo;
131 createParam.saIpSecParam.esnHi = sa_info->esnHi;
132 memcpy(&createParam.keyParam,key_params,sizeof(nwalSecKeyParams_t));
134 if (route != NULL)
135 {
136 netcp_cfgp_build_route(route,&createParam.saIpSecParam.appRxPktFlowId,
137 &createParam.saIpSecParam.appRxPktQueue);
138 }
140 //fire off config message
141 pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
142 retValue = nwal_setSecAssoc (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
143 trans_id,
144 (nwal_AppId) appId,
145 &saInfo,
146 &createParam,
147 &pTransInfo->handle);
148 if(retValue == nwal_TRANS_COMPLETE)
149 {
150 have_to_wait=0;
151 }
152 else if(retValue != nwal_OK)
153 {
154 *perr = NETAPI_ERR_NWAL_ERR0;
155 printf (">netapi_sec - ERROR: nwal_setSecAssoc returned Error Code %d\n",
156 retValue);
157 pTransInfo->inUse = nwal_FALSE;
158 netcp_cfgp_delete_sa(&netapi_get_global()->nwal_context,tunnelId);
159 return -1;
160 }
161 //pTransInfo->inUse = nwal_FALSE;
163 //wait here until its done since scheduler isn't running yet most likely..
164 // todo: make this handled by scheduler poll later ??
165 if((trans_id != NWAL_TRANSID_SPIN_WAIT)&&(have_to_wait))
166 {
167 n->nwal_local.numPendingCfg++;
168 while ((volatile) n->nwal_local.numPendingCfg)
169 {
170 // if response is there, then this poll squirts out in the CTl poll callback,
171 // which handles the rest (including decrmenting #pending!!
172 nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
173 }
174 }
175 printf (">netapi sec: SA %d added to mac %d\n", tunnelId, iface_no);
177 pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
178 *p_inflow_mode_handle=pTransInfo->handle;
179 pTransInfo->inUse = nwal_FALSE;
180 }
182 //sideband mode
183 if (inflow_mode &NETAPI_SEC_SA_SIDEBAND)
184 {
185 nwalCreateDmSAParams_t dmSaParam;
186 void * dm_handle;
187 memset(&dmSaParam,0,sizeof(nwalCreateDmSAParams_t));
188 dmSaParam.dmSaParam.dmChnType= (sa_info->dir==NWAL_SA_DIR_INBOUND)? NWAL_DM_CHAN_DECRYPT: NWAL_DM_CHAN_ENCRYPT; /**direction*/
189 dmSaParam.dmSaParam.replayWindow=sa_info->replayWindow; /**< Replay Window Size */
190 dmSaParam.dmSaParam.authMode=sa_info->authMode; /**< Authentication Algorithm */
191 dmSaParam.dmSaParam.cipherMode=sa_info->cipherMode ; /**< Encryption Algorithm */
192 dmSaParam.dmSaParam.macSize=12; /**todo: pass in or deduce */
193 dmSaParam.dmSaParam.aadSize=0; /**todo: pass in or deduce */
194 dmSaParam.dmSaParam.enc1st = (sa_info->dir ==NWAL_SA_DIR_OUTBOUND) ? nwal_TRUE : nwal_FALSE; //encypt 1st for outbound
195 //todo; allow app q for Sideband return
196 dmSaParam.dmSaParam.appRxPktFlowId= CPPI_PARAM_NOT_SPECIFIED;
197 dmSaParam.dmSaParam.appRxPktQueue= CPPI_PARAM_NOT_SPECIFIED;
198 memcpy(&dmSaParam.keyParam,key_params,sizeof(nwalSecKeyParams_t));
199 retValue = nwal_setDMSecAssoc(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
200 (nwal_AppId)appId,
201 &dmSaParam,
202 &dm_handle);
203 if(retValue != nwal_OK)
204 {
205 *perr = NETAPI_ERR_NWAL_ERR0;
206 printf (">netapi_sec - ERROR: nwal_setDMSecAssoc returned Error Code %d\n",
207 retValue);
208 netcp_cfgp_delete_sa(&netapi_get_global()->nwal_context,tunnelId);
209 return -1;
210 }
211 printf(">netapisec. Creating sideband mode SA for %d ( mac %d)\n", tunnelId, iface_no);
212 *p_data_mode_handle = dm_handle;
213 }
214 //save stuff
215 netcp_cfgp_insert_sa(&netapi_get_global()->nwal_context,
216 tunnelId,
217 (sa_info->dir == NWAL_SA_DIR_INBOUND) ? TRUE: FALSE,
218 inflow_mode,
219 &saInfo, &createParam,
220 *p_inflow_mode_handle,
221 *p_data_mode_handle);
222 return (appId);
223 }
225 //enable or disable inflow mode
226 void netapi_secInflowMode(int iface, NETCP_CFG_SA_T sa, int on)
227 {
228 /*todo */ /* FUTURE */
229 printf(">netapi_sec: dynamic switch between inflow and sideband is not functional yet\n");
230 }
232 //delete the SA
233 //(internal version)
234 static void netapi_secDelSA_internal(NETAPI_T h,int iface_no, NETCP_CFG_SA_T sa_app_id, int flags, int *perr)
235 {
236 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
237 nwal_RetValue retValue;
238 NetapiNwalTransInfo_t *pTransInfo;
239 nwal_TransID_t trans_id;
240 int tunnelId = (sa_app_id >>8) &0xffff;
241 void * handle_inflow;
242 void * handle_sideband;
243 int have_to_wait = 1;
245 handle_inflow = netcp_cfgp_get_sa_handles(&netapi_get_global()->nwal_context,
246 tunnelId, &handle_sideband);
247 *perr =0;
249 if(handle_inflow)
250 {
251 //get a transaction id
252 pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);
253 if (!pTransInfo) { *perr = NETAPI_ERR_BUSY; return ;}
254 pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA;
255 pTransInfo->netapi_handle = h;
257 //issue request
258 retValue = nwal_delSecAssoc(
259 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
260 trans_id,
261 handle_inflow);
262 if(retValue == nwal_TRANS_COMPLETE)
263 {
264 have_to_wait=0;
265 }
266 else
267 if(retValue != nwal_OK)
268 {
269 *perr = NETAPI_ERR_NWAL_ERR0;
270 printf (">netapi_sec - ERROR: nwal_delSA returned Error Code %d\n",
271 retValue);
272 pTransInfo->inUse = nwal_FALSE;
273 return ;
274 }
275 //wait here until its done since scheduler isn't running yet most likely..
276 // todo: make this handled by scheduler poll later ??
277 if((trans_id != NWAL_TRANSID_SPIN_WAIT)&&(have_to_wait))
278 {
279 n->nwal_local.numPendingCfg++;
280 while ((volatile) n->nwal_local.numPendingCfg)
281 {
282 // if response is there, then this poll squirts out in the CTl poll callback,
283 // which handles the rest (including decrmenting #pending!!
284 nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
285 }
286 }
287 printf (">netapi sec: inflow tunnel %d (iface %d) deleted\n",tunnelId,iface_no);
288 pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
289 pTransInfo->inUse = nwal_FALSE;
290 }
291 if (handle_sideband)
292 {
293 retValue=nwal_delDMSecAssoc( ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
294 handle_sideband);
295 if(retValue != nwal_OK)
296 {
297 *perr = NETAPI_ERR_NWAL_ERR0;
298 printf (">netapi_sec - ERROR: nwal_delDMSA returned Error Code %d\n",
299 retValue);
301 }
302 else printf(">netapi_sec: Sideband SA deleted\n");
303 }
305 //zap the entry
306 if (!flags) netcp_cfgp_delete_sa(&netapi_get_global()->nwal_context, tunnelId);
307 }
308 //external version
309 void netapi_secDelSA(NETAPI_T h,int iface_no, NETCP_CFG_SA_T sa_app_id, int *perr)
310 {
311 netapi_secDelSA_internal( h, iface_no, sa_app_id, 0x00, perr);
312 }
315 //******************************************
316 // Add Policy
317 //******************************************
318 NETCP_CFG_IPSEC_POLICY_T netapi_secAddRxPolicy(NETAPI_T h, //the netapi handle
319 NETCP_CFG_SA_T sa, //tunnel to attach to
320 nwal_IpType ipType, //V4 or V6
321 nwalIpAddr_t * src_ip_addr, //src (from where)
322 nwalIpAddr_t * dst_ip_addr, //dst (us)
323 nwalIpOpt_t * ip_qualifiers, //other qualifiers
324 NETCP_CFG_ROUTE_HANDLE_T route, //Optional route
325 int * perr)
326 {
327 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
328 nwal_RetValue retValue;
329 NetapiNwalTransInfo_t *pTransInfo;
330 nwal_TransID_t trans_id;
331 unsigned int appId = NETAPI_NETCP_MATCH_IPSEC_POLICY | (sa&0xff);
332 int policyId;
333 int tunnelId= (sa>>8)&0xff;
334 void * blah;
335 int iface_no = sa&0xff;
336 nwalSecPolParams_t createParam =
337 {
338 0, /* handle */
339 NWAL_SA_DIR_INBOUND,
340 4, /* IP Type */
341 {0}, /* dst */
342 {0}, /* src */
343 {0 },/* IP Options */
344 NWAL_MATCH_ACTION_CONTINUE_NEXT_ROUTE, /* Continue parsing to next route for match */
345 NWAL_NEXT_ROUTE_FAIL_ACTION_HOST, /* For next route fail action by default is route to host */
346 CPPI_PARAM_NOT_SPECIFIED, /* Use default flow configured to NWAL if packet is routed to host */
347 QMSS_PARAM_NOT_SPECIFIED /* Use default queue configured to NWAL if packet is routed to host */
348 };
349 void * sa_handle = NULL;
351 *perr =0;
352 if ((!n) ) {*perr = NETAPI_ERR_BAD_INPUT; return -1;}
354 sa_handle = netcp_cfgp_get_sa_handles(&netapi_get_global()->nwal_context,tunnelId,&blah);
355 if (!sa_handle) {*perr = NETAPI_ERR_BAD_INPUT; return -1;}
357 pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);
358 if (!pTransInfo) { *perr = NETAPI_ERR_BUSY; return -1;}
359 pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA_POLICY;
360 pTransInfo->netapi_handle = h;
361 createParam.handle = sa_handle;
362 createParam.ipType = ipType;
363 if (dst_ip_addr) memcpy(&createParam.dst, dst_ip_addr, sizeof(nwalIpAddr_t));
364 if (src_ip_addr) memcpy(&createParam.src, src_ip_addr, sizeof(nwalIpAddr_t));
365 if (ip_qualifiers) memcpy(&createParam.ipOpt,ip_qualifiers ,sizeof(nwalIpOpt_t));
366 if (route != NULL)
367 {
368 netcp_cfgp_build_route(route,&createParam.appRxPktFlowId,
369 &createParam.appRxPktQueue);
370 }
371 //reserve a slot
372 policyId = netcp_cfgp_find_policy_slot(&netapi_get_global()->nwal_context,
373 tunnelId);
374 if (policyId <0) {*perr= NETAPI_ERR_NOMEM; return -1; }
375 appId |= (policyId<<8);
377 //fire off config message
378 pTransInfo->state == NETAPI_NWAL_HANDLE_STATE_OPEN_PENDING;
380 retValue = nwal_setSecPolicy (((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
381 trans_id,
382 (nwal_AppId) appId,
383 &createParam,
384 &pTransInfo->handle);
385 if(retValue != nwal_OK)
386 {
387 *perr = NETAPI_ERR_NWAL_ERR0;
388 printf (">netapi sec - ERROR: nwal_setPolicy returned Error Code %d\n",
389 retValue);
390 pTransInfo->inUse = nwal_FALSE;
391 netcp_cfgp_delete_policy(&netapi_get_global()->nwal_context,policyId);
392 return -1;
393 }
394 //pTransInfo->inUse = nwal_FALSE;
396 //wait here until its done since scheduler isn't running yet most likely..
397 // todo: make this handled by scheduler poll later ??
398 if(trans_id != NWAL_TRANSID_SPIN_WAIT)
399 {
400 n->nwal_local.numPendingCfg++;
401 while ((volatile) n->nwal_local.numPendingCfg)
402 {
403 // if response is there, then this poll squirts out in the CTl poll callback,
404 // which handles the rest (including decrmenting #pending!!
405 nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
406 }
407 }
408 printf (">netapi sec: SA %d added to tunnel %d mac %d\n", policyId, tunnelId, iface_no);
410 //todo: the sideband i/f
412 //save stuff
413 netcp_cfgp_insert_policy(&netapi_get_global()->nwal_context,
414 policyId,
415 (void *) pTransInfo->handle);
416 pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
417 pTransInfo->inUse = nwal_FALSE;
418 return (appId);
419 }
421 //************************
422 //Delete Policy (internal)
423 //***********************
424 static void netapi_secDelRxPolicy_internal(NETAPI_T h, NETCP_CFG_IPSEC_POLICY_T policy_app_id, int flags, int *perr)
425 {
426 NETAPI_HANDLE_T * n = (NETAPI_HANDLE_T *) h;
427 nwal_RetValue retValue;
428 NetapiNwalTransInfo_t *pTransInfo;
429 nwal_TransID_t trans_id;
430 int policyId = (policy_app_id >>8) &0xffff;
431 void * handle_policy=NULL;
433 handle_policy = netcp_cfgp_get_policy(&netapi_get_global()->nwal_context,policyId);
434 ;
435 if (!handle_policy) {*perr = NETAPI_ERR_BAD_INPUT; return ;}
436 *perr =0;
438 //get a transaction id
439 pTransInfo = netapip_GetFreeTransInfo((NETAPI_GLOBAL_T *) n->global, &trans_id);
440 if (!pTransInfo) { *perr = NETAPI_ERR_BUSY; return ;}
441 pTransInfo->transType = NETAPI_NWAL_HANDLE_TRANS_SA_POLICY;
442 pTransInfo->netapi_handle = h;
444 //issue request
445 retValue = nwal_delSecPolicy(
446 ((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,
447 trans_id,
448 handle_policy);
449 if(retValue != nwal_OK)
450 {
451 *perr = NETAPI_ERR_NWAL_ERR0;
452 printf (">netsec - ERROR: nwal_delSAPolicy returned Error Code %d\n",
453 retValue);
454 pTransInfo->inUse = nwal_FALSE;
455 return ;
456 }
457 //wait here until its done since scheduler isn't running yet most likely..
458 // todo: make this handled by scheduler poll later ??
459 if(trans_id != NWAL_TRANSID_SPIN_WAIT)
460 {
461 n->nwal_local.numPendingCfg++;
462 while ((volatile) n->nwal_local.numPendingCfg)
463 {
464 // if response is there, then this poll squirts out in the CTl poll callback,
465 // which handles the rest (including decrmenting #pending!!
466 nwal_pollCtl(((NETAPI_GLOBAL_T*) (n->global))->nwal_context.nwalInstHandle,NULL,NULL);
467 }
468 }
469 printf (">netapi sec: policy %d (iface %d) deleted\n",policyId,(policy_app_id&0xff));
470 pTransInfo->state = NETAPI_NWAL_HANDLE_STATE_IDLE;
471 pTransInfo->inUse = nwal_FALSE;
472 //zap the entry
473 if (!flags) netcp_cfgp_delete_policy(&netapi_get_global()->nwal_context, policyId);
474 }
476 //************************
477 //Delete Policy
478 //***********************
479 void netapi_secDelRxPolicy(NETAPI_T h, NETCP_CFG_IPSEC_POLICY_T policy_app_id, int *perr)
480 {
481 netapi_secDelRxPolicy_internal(h, policy_app_id, 0, perr);
482 }