Modify licenses
[scp/ocu/5gnr.git] / Cu / CuUp / Pdcp / PdcpUp / Src / pdcpuUpc.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 ICT/CAS.
4 *
5 *   Licensed under the O-RAN Software License, Version 1.0 (the "Software License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       https://www.o-ran.org/software
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 #include "vos_types.h"
20 #include "vos_string.h"
21 #include "vos_lib.h"
22 #include "pdcpu.h"
23 #include "pdcpuCore.h"
24 #include "pdcpCommon.h"
25 #include "cuupCommon.h"
26 #include "cuModuleInterface.h"
27 #include "pdcpComprohc.h"
28 #include "cuupTest.h"
29 #include "cuupUeIdTransf.h"
30 #include "upcContext.h"
31
32 extern PdcpuUeInfo_t *gPdcpuUeInfo[MAX_UE_NUM];
33 ULONG gPdcpuModuleId;
34 CuupUeIdxTable_t gPdcpuUeIdxTable;
35
36
37 /*******************************************************************************
38 * To
39 * INPUT:
40 *         :
41 * OUTPUT:
42 *        0:success
43 *       -1:fail
44 *******************************************************************************/
45 INT32 pdcpuInit(ULONG userModuleId)
46 {
47         /* get pdcpu moduleId */
48         gPdcpuModuleId = userModuleId;
49
50         /* init ueIdx table */
51         UINT8 i = 0;
52         for(i=0; i<MAX_UE_NUM; i++)
53         {
54                 gPdcpuUeIdxTable.ueIdxInfo[i].isUsed = FALSE;
55         }
56
57         /* init ue info */
58         for(i=0; i<MAX_UE_NUM; i++)
59         {
60                 gPdcpuUeInfo[i] = NULL;
61         }
62
63         return VOS_OK;
64 }
65
66
67 INT32 pdcpuFreeSecInfo(UINT16 ueIdx)
68 {
69         PdcpuSecInfo_t *pDrbSecInfo = gPdcpuUeInfo[ueIdx]->secInfo;
70         if(NULL != pDrbSecInfo)
71         {
72                 VOS_Free(pDrbSecInfo);
73                 gPdcpuUeInfo[ueIdx]->secInfo = NULL;
74         }
75
76         return VOS_OK;
77 }
78
79 /*******************************************************************************
80 * To deal with security indication
81 * Security Result indicates whether the security policy indicated as "preferred"
82 * in the Security Indication IE is performed or not.
83 * INPUT:
84 *        ueE1apId : UE E1AP ID
85 *        pduSessionId : pdu session id
86 *        pSecInd : security indication
87 *        pSecResult : security result
88 * OUTPUT:
89 *        0:success
90 *       -1:fail
91 *******************************************************************************/
92 INT32 pdcpuDealSecurityInd(PdcpuSecInfo_t *pSec, PdcpuSecEnableInfo_t *pEnableInfo, SecuInd_t *pSecInd, PdcpuCfgResult_t *pResult)
93 {
94         /* get security enable information global variable */
95         pdcpuNullCheck(pSec);
96         pdcpuNullCheck(pEnableInfo);
97         pdcpuNullCheck(pSecInd);
98
99         /* for integrity protection */
100         if(ACTIVE_INT_STATE == pSec->intActiveFlag)
101         {
102                 /* integrity protection is active for the UE, apply the indication */
103                 if(IP_REQUIRED == pSecInd->IPIndication)
104                 {
105                         pEnableInfo->integrityEnableFlag = TRUE;
106                         pEnableInfo->maxIPDataRate               = pSecInd->maxIPdataRate;
107                         pResult->secResPresent                   = FALSE;
108
109                 }else if(IP_PREFERRED == pSecInd->IPIndication)
110                 {
111                         pEnableInfo->integrityEnableFlag = TRUE;
112                         pEnableInfo->maxIPDataRate               = pSecInd->maxIPdataRate;
113                         pResult->secResPresent                   = TRUE;
114                         pResult->secuResult.integrityProtectionResult= IP_RESULT_PERFORMED;
115
116                 }else
117                 {
118                         pEnableInfo->integrityEnableFlag = FALSE;
119                         pResult->secResPresent                   = FALSE;
120
121                 }
122
123         }else
124         {
125                 /* integrity protection is inactive for the UE */
126                 pEnableInfo->integrityEnableFlag = FALSE;
127                 if(IP_PREFERRED == pSecInd->IPIndication)
128                 {
129                         pResult->secResPresent = TRUE;
130                         pResult->secuResult.integrityProtectionResult= IP_RESULT_NOT_PERFORMED;
131                 }
132         }
133
134         /* for ciphering */
135         if(ACTIVE_ENC_STATE == pSec->encActiveFlag)
136         {
137                 /* ciphering is active for the UE, apply the indication */
138                 if(CP_REQUIRED == pSecInd->CPIndication)
139                 {
140                         pEnableInfo->cipherEnableFlag = TRUE;
141                         pResult->secResPresent            = FALSE;
142
143                 }else if(CP_PREFERRED == pSecInd->CPIndication)
144                 {
145                         pEnableInfo->cipherEnableFlag = TRUE;
146                         pResult->secResPresent            = TRUE;
147                         pResult->secuResult.confidentialityProtectionResult = CP_RESULT_PERFORMED;
148
149                 }else
150                 {
151                         pEnableInfo->cipherEnableFlag = FALSE;
152                         pResult->secResPresent            = FALSE;
153
154                 }
155
156         }else
157         {
158                 /* ciphering is inactive for the UE */
159                 pEnableInfo->cipherEnableFlag = FALSE;
160                 if(CP_PREFERRED == pSecInd->CPIndication)
161                 {
162                         pResult->secResPresent = TRUE;
163                         pResult->secuResult.confidentialityProtectionResult= CP_RESULT_NOT_PERFORMED;
164                 }
165         }
166
167         return VOS_OK;
168 }
169
170 INT32 pdcpuRetFailResult(UpcCfgType_e cfgType, upcTempSessInfo_t *pCfgInfo, PdcpuCfgResult_t *pResult)
171 {
172         pdcpuLog(LOG_ERR,"[PDCPU] pdu session config failed\n");
173
174         UINT8 i = 0;
175         if(PDU_SESSION_ADD == cfgType)
176         {
177                 /* drb to setup list */
178                 for(i=0; i<pCfgInfo->drbSetupNum; i++)
179                 {
180                         pResult->drbSetupFailedArray[i].drbId = pCfgInfo->pTempDrbSetupList[i].drbId;
181                         pResult->drbSetupFailedArray[i].cause = RNL_UNSPECIFIED;
182                 }
183                 pResult->drbSetupFailNum = pCfgInfo->drbSetupNum;
184                 pResult->pduSessionCause = RNL_UNSPECIFIED;
185
186         }
187
188
189         return VOS_ERROR;
190 }
191
192 /*******************************************************************************
193 * To deal with PDU session to setup config
194 * INPUT:
195 *        ueE1apId : UE E1AP ID
196 *        pPduSessionCfg : PDU session to setup config
197 *        pResult : PDU session to setup result
198 * OUTPUT:
199 *        none
200 *******************************************************************************/
201 INT32 pdcpuSessionAddProc(UINT64 ueE1apId, VOID *pCfgInfo, PdcpuCfgResult_t *pResult)
202 {
203         upcTempSessInfo_t *pSetupInfo = (upcTempSessInfo_t *)pCfgInfo;
204         upcTempDrbInfo_t  *pDrbTemp   = NULL;
205         PdcpuSecInfo_t           *pSec            = NULL;
206         PdcpuSecEnableInfo_t *pEnableInfo = NULL;
207
208         UINT16 pduSessionId = pSetupInfo->pduSessId;
209         pResult->pduSessionId = pduSessionId;
210
211         /* get ueIdx */
212         UINT16 ueIdx;
213         if(VOS_ERROR == cuupAddUeE1apid(ueE1apId, &ueIdx, &gPdcpuUeIdxTable))
214         {
215                 pdcpuLog(LOG_ERR,"[PDCPU] add ueE1apId failed\n");
216                 return pdcpuRetFailResult(PDU_SESSION_ADD,pCfgInfo,pResult);
217         }
218
219         /* check ue and security context block */
220         if((NULL == gPdcpuUeInfo[ueIdx]) || (NULL == gPdcpuUeInfo[ueIdx]->secInfo))
221         {
222                 pdcpuLog(LOG_ERR,"[PDCPU] ue and security context block not exist\n");
223                 return pdcpuRetFailResult(PDU_SESSION_ADD,pCfgInfo,pResult);
224         }
225         pSec = gPdcpuUeInfo[ueIdx]->secInfo;
226
227         /* alloc pdu session information */
228         pEnableInfo = gPdcpuUeInfo[ueIdx]->secEnableInfo[pduSessionId];
229         if(NULL == pEnableInfo)
230         {
231                 pEnableInfo = VOS_Malloc(sizeof(PdcpuSecEnableInfo_t), gPdcpuModuleId);
232                 if(NULL == pEnableInfo)
233                 {
234                         pdcpuLog(LOG_ERR,"[PDCPU] vos_malloc failed\n");
235                         return pdcpuRetFailResult(PDU_SESSION_ADD,pCfgInfo,pResult);
236                 }
237                 VOS_MemZero(pEnableInfo, sizeof(PdcpuSecEnableInfo_t));
238                 gPdcpuUeInfo[ueIdx]->secEnableInfo[pduSessionId] = pEnableInfo;
239         }
240         pEnableInfo->pduSessionId = pduSessionId;
241
242         /* deal with security indication */
243         if(VOS_ERROR == pdcpuDealSecurityInd(pSec, pEnableInfo, &pSetupInfo->secuIndi, pResult))
244         {
245                 pdcpuLog(LOG_ERR,"[PDCPU] deal security indication failed\n");
246                 return pdcpuRetFailResult(PDU_SESSION_ADD,pCfgInfo,pResult);
247         }
248
249         /* create pdcp entity */
250         UINT8 i = 0;
251         for(i = 0; i < pSetupInfo->drbSetupNum; i++)
252         {
253                 pDrbTemp = &pSetupInfo->pTempDrbSetupList[i];
254
255                 if((NULL == pDrbTemp) || (FALSE == pDrbTemp->drbSetupAllowed))
256                 {
257                         continue;
258                 }
259
260                 if(VOS_OK == pdcpuCreateEntity(ueE1apId, ueIdx, pduSessionId, pDrbTemp))
261                 {
262                         pResult->drbSetupSuccessArray[pResult->drbSetupSuccessNum] = pDrbTemp->drbId;
263                         pResult->drbSetupSuccessNum += 1;
264                 }else
265                 {
266                         pResult->drbSetupFailedArray[pResult->drbSetupFailNum].drbId = pDrbTemp->drbId;
267                         pResult->drbSetupFailedArray[pResult->drbSetupFailNum].cause = RNL_PDCP_CONFIG_NOT_SUPPORT;
268                         pResult->drbSetupFailNum += 1;
269
270                 }
271         }
272
273         /* return */
274         if(0 != pResult->drbSetupSuccessNum)
275         {
276                 return VOS_OK;
277         }else
278         {
279                 pResult->pduSessionCause = RNL_UNSPECIFIED;
280                 pdcpuLog(LOG_ERR,"[PDCPU] all drbs setup failed\n");
281                 return VOS_ERROR;
282         }
283 }
284
285 /*******************************************************************************
286  * To manage pdcp-u entity
287  * INPUT:
288  *              ueE1apId                : UE E1AP ID
289  *              pPduSessionCfg  : PDU Session Resource to setup item
290  *              cfgType                 : configuration type
291  *              pResult                 : result which will return to upc
292  * OUTPUT:
293  *              result: PDCP config result
294  *******************************************************************************/
295 INT32 pdcpuConfig(UINT64 ueE1apId, VOID *pCfgInfo, UpcCfgType_e cfgType, PdcpuCfgResult_t *pResult)
296 {
297         switch(cfgType)
298         {
299                 case PDU_SESSION_ADD:
300                 {
301                         pdcpuNullCheck(pCfgInfo);
302                         pdcpuNullCheck(pResult);
303                         VOS_MemZero(pResult, sizeof(PdcpuCfgResult_t));
304                         pResult->cfgType = cfgType;
305                         return pdcpuSessionAddProc(ueE1apId, pCfgInfo, pResult);
306                 }
307                 default:
308                 {
309                         pdcpuLog(LOG_ERR,"[PDCPU] cfgType error\n");
310                         return VOS_ERROR;
311                 }
312         }
313
314 }
315
316
317 /*******************************************************************************
318  * To get ue security information pointer
319  * INPUT:
320  *              ueIdx: UE index
321  * OUTPUT:
322  *              pDrbSecInfo: ue security information pointer
323  *******************************************************************************/
324 PdcpuSecInfo_t *pdcpuAllocUeSecInfo(UINT16 ueIdx)
325 {
326         PdcpuSecInfo_t *pSecInfo        = NULL;
327         PdcpuUeInfo_t  *pPdcpUeInfo = NULL;
328
329         //check ue
330         if(NULL == gPdcpuUeInfo[ueIdx])
331         {
332                 pPdcpUeInfo = VOS_Malloc(sizeof(PdcpuUeInfo_t), gPdcpuModuleId);
333                 pdcpuNullCheckRp(pPdcpUeInfo);
334                 VOS_MemZero(pPdcpUeInfo, sizeof(PdcpuUeInfo_t));
335                 gPdcpuUeInfo[ueIdx] = pPdcpUeInfo;
336         }else
337         {
338                 pPdcpUeInfo = gPdcpuUeInfo[ueIdx];
339         }
340         //check secInfo
341         if(NULL == pPdcpUeInfo->secInfo)
342         {
343                 pSecInfo = VOS_Malloc(sizeof(PdcpuSecInfo_t), gPdcpuModuleId);
344                 pdcpuNullCheckRp(pSecInfo);
345                 VOS_MemZero(pSecInfo, sizeof(PdcpuSecInfo_t));
346                 pPdcpUeInfo->secInfo = pSecInfo;
347         }else
348         {
349                 pSecInfo = pPdcpUeInfo->secInfo;
350         }
351
352         VOS_MemZero(pSecInfo, sizeof(PdcpuSecInfo_t));
353
354         return pSecInfo;
355 }
356
357
358 /*******************************************************************************
359  * To set ue security parameters. When receiving security information,
360  * pdcp-u shall save AS keys, AS algorithm and active integrity and ciphering.
361  * INPUT:
362  *              ueE1apId: UE E1AP ID
363  *              secInfo: security information
364  * OUTPUT:
365  *              0: success
366  *              -1:failed
367  *******************************************************************************/
368 INT32 pdcpuSetSecParam(UINT64 ueE1apId, SecuInfo_t *secInfo)
369 {
370         pdcpuNullCheck(secInfo);
371
372         UINT16 ueIdx;
373         if(VOS_ERROR == cuupAddUeE1apid(ueE1apId, &ueIdx, &gPdcpuUeIdxTable))
374         {
375                 pdcpuLog(LOG_ERR,"[PDCPU] add ueE1apId failed\n");
376                 return VOS_ERROR;
377         }
378
379         /* find ue security struct */
380         PdcpuSecInfo_t *pDrbSecInfo = pdcpuAllocUeSecInfo(ueIdx);
381         pdcpuNullCheck(pDrbSecInfo);
382
383         /* activate integrity */
384         if(secInfo->secuAlgorithm.bitMask & SECURITY_ALGORITHM_INTERGRITY_PROTECTION_ALGORITHM)
385         {
386                 UINT8  intAlgorithm = secInfo->secuAlgorithm.integrityProtectionAlgorithm;
387                 UINT8 *pIntKey          = secInfo->upSecukey.integrityProtectionKey.buffer;
388                 UINT8  intKeyLen        = secInfo->upSecukey.integrityProtectionKey.size;       /* 128 bits */
389
390                 if(intKeyLen < AS_KEY_LEN)
391                 {
392                         pdcpuLog(LOG_ERR,"[PDCPU] integrity parameter is wrong!\n");
393                         pdcpuFreeSecInfo(ueIdx);
394                         return VOS_ERROR;
395                 }
396
397                 pDrbSecInfo->intActiveFlag = ACTIVE_INT_STATE;                                  /* 0-inactive, 1-active */
398                 if(intAlgorithm == NIA0 || intAlgorithm == NIA1 || intAlgorithm == NIA2)
399                 {
400                         pDrbSecInfo->intAlgorithm  = intAlgorithm;
401                         VOS_MemCpy(pDrbSecInfo->kUpInt, pIntKey, AS_KEY_LEN);           /* 128 bits */
402                 }else
403                 {
404                         pDrbSecInfo->intActiveFlag = INACTIVE_INT_STATE;
405                         pdcpuLog(LOG_ERR,"[PDCPU] integrity algorithm is %d, not supported!\n",intAlgorithm);
406                         pdcpuFreeSecInfo(ueIdx);
407                         return VOS_ERROR;
408                 }
409         }else
410         {
411                 pDrbSecInfo->intActiveFlag = INACTIVE_INT_STATE;
412                 pdcpuLog(LOG_INFO,"[PDCPU] integrity is not config\n");
413         }
414
415         /* activate encryption */
416         UINT8  encAlgorithm = secInfo->secuAlgorithm.cipheringAlgorithm;
417         UINT8 *pEncKey          = secInfo->upSecukey.encryptionKey.buffer;
418         UINT8  encKeyLen        = secInfo->upSecukey.encryptionKey.size;                /* 128 bits */
419
420         if(encKeyLen < AS_KEY_LEN)
421         {
422                 pdcpuLog(LOG_ERR,"[PDCPU] encryption parameter is wrong!\n");
423                 pdcpuFreeSecInfo(ueIdx);
424                 return VOS_ERROR;
425         }
426
427         pDrbSecInfo->encActiveFlag = ACTIVE_ENC_STATE;                                          /* 0-inactive, 1-active */
428         if(encAlgorithm == NEA0 || encAlgorithm == NEA1 || encAlgorithm == NEA2)
429         {
430                 pDrbSecInfo->encAlgorithm  = encAlgorithm;
431                 VOS_MemCpy(pDrbSecInfo->kUpEnc, pEncKey, AS_KEY_LEN);                   /* 128 bits */
432         }else
433         {
434                 pDrbSecInfo->encActiveFlag = INACTIVE_ENC_STATE;
435                 pdcpuLog(LOG_ERR,"[PDCPU] encryption algorithm:%d, is not supported!\n", encAlgorithm);
436                 pdcpuFreeSecInfo(ueIdx);
437                 return VOS_ERROR;
438         }
439
440         pDrbSecInfo->ueE1apId = ueE1apId;
441         pDrbSecInfo->ueIdx        = ueIdx;
442         pDrbSecInfo->nhInd        = FALSE;
443
444         return VOS_OK;
445 }