Merge remote-tracking branch 'origin/develop' into develop-SA-CBRA
# Conflicts: # openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c # openair2/LAYER2/NR_MAC_gNB/mac_proto.h
This commit is contained in:
@@ -155,6 +155,11 @@ typedef struct security_capabilities_s {
|
||||
uint16_t integrity_algorithms;
|
||||
} security_capabilities_t;
|
||||
|
||||
typedef struct nr_security_capabilities_s {
|
||||
uint16_t encryption_algorithms;
|
||||
uint16_t integrity_algorithms;
|
||||
} nr_security_capabilities_t;
|
||||
|
||||
/* Provides the establishment cause for the RRC connection request as provided
|
||||
* by the upper layers. W.r.t. the cause value names: highPriorityAccess
|
||||
* concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for
|
||||
@@ -538,6 +543,9 @@ typedef struct s1ap_initial_context_setup_req_s {
|
||||
uint8_t nb_of_e_rabs;
|
||||
/* list of e_rab to be setup by RRC layers */
|
||||
e_rab_t e_rab_param[S1AP_MAX_E_RAB];
|
||||
|
||||
/* NR Security algorithms (if any, set to 0 if not present) */
|
||||
nr_security_capabilities_t nr_security_capabilities;
|
||||
} s1ap_initial_context_setup_req_t;
|
||||
|
||||
typedef struct tai_plmn_identity_s {
|
||||
|
||||
@@ -338,7 +338,7 @@ typedef struct x2ap_ENDC_sgnb_addition_req_s {
|
||||
/* used for RRC->X2AP in source eNB */
|
||||
int rnti;
|
||||
|
||||
security_capabilities_t security_capabilities;
|
||||
nr_security_capabilities_t security_capabilities;
|
||||
|
||||
/* SgNB Security Key */
|
||||
uint8_t kgnb[32];
|
||||
|
||||
@@ -163,6 +163,8 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) {
|
||||
// scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB_SUL = CALLOC(1,sizeof(NR_RSRP_Range_t));
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t));
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = CALLOC(1,sizeof(long));
|
||||
// 0 - ENABLE, 1 - DISABLE, hence explicitly setting to DISABLED.
|
||||
*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled;
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_PUSCH_ConfigCommon_t));
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->present = NR_SetupRelease_PUSCH_ConfigCommon_PR_setup;
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PUSCH_ConfigCommon));
|
||||
@@ -513,6 +515,101 @@ void RCconfig_nr_macrlc() {
|
||||
|
||||
}
|
||||
|
||||
void config_security(gNB_RRC_INST *rrc)
|
||||
{
|
||||
paramdef_t logparams_defaults[] = SECURITY_GLOBALPARAMS_DESC;
|
||||
int ret = config_get(logparams_defaults,
|
||||
sizeof(logparams_defaults) / sizeof(paramdef_t),
|
||||
CONFIG_STRING_SECURITY);
|
||||
int i;
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_W(RRC, "configuration file does not contain a \"security\" section, applying default parameters (no security)\n");
|
||||
rrc->security.ciphering_algorithms[0] = 0; /* nea0 = no ciphering */
|
||||
rrc->security.ciphering_algorithms_count = 1;
|
||||
rrc->security.integrity_algorithms[0] = 0; /* nia0 = no integrity */
|
||||
rrc->security.integrity_algorithms_count = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].numelt > 4) {
|
||||
LOG_E(RRC, "too much ciphering algorithms in section \"security\" of the configuration file, maximum is 4\n");
|
||||
exit(1);
|
||||
}
|
||||
if (logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].numelt > 4) {
|
||||
LOG_E(RRC, "too much integrity algorithms in section \"security\" of the configuration file, maximum is 4\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* get ciphering algorithms */
|
||||
rrc->security.ciphering_algorithms_count = 0;
|
||||
for (i = 0; i < logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].numelt; i++) {
|
||||
if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea0")) {
|
||||
rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 0;
|
||||
rrc->security.ciphering_algorithms_count++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea1")) {
|
||||
rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 1;
|
||||
rrc->security.ciphering_algorithms_count++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea2")) {
|
||||
rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 2;
|
||||
rrc->security.ciphering_algorithms_count++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea3")) {
|
||||
rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 3;
|
||||
rrc->security.ciphering_algorithms_count++;
|
||||
continue;
|
||||
}
|
||||
LOG_E(RRC, "unknown ciphering algorithm \"%s\" in section \"security\" of the configuration file\n",
|
||||
logparams_defaults[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* get integrity algorithms */
|
||||
rrc->security.integrity_algorithms_count = 0;
|
||||
for (i = 0; i < logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].numelt; i++) {
|
||||
if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia0")) {
|
||||
rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 0;
|
||||
rrc->security.integrity_algorithms_count++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia1")) {
|
||||
rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 1;
|
||||
rrc->security.integrity_algorithms_count++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia2")) {
|
||||
rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 2;
|
||||
rrc->security.integrity_algorithms_count++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia3")) {
|
||||
rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 3;
|
||||
rrc->security.integrity_algorithms_count++;
|
||||
continue;
|
||||
}
|
||||
LOG_E(RRC, "unknown integrity algorithm \"%s\" in section \"security\" of the configuration file\n",
|
||||
logparams_defaults[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (rrc->security.ciphering_algorithms_count == 0) {
|
||||
LOG_W(RRC, "no preferred ciphering algorithm set in configuration file, applying default parameters (no security)\n");
|
||||
rrc->security.ciphering_algorithms[0] = 0; /* nea0 = no ciphering */
|
||||
rrc->security.ciphering_algorithms_count = 1;
|
||||
}
|
||||
|
||||
if (rrc->security.integrity_algorithms_count == 0) {
|
||||
LOG_W(RRC, "no preferred integrity algorithm set in configuration file, applying default parameters (no security)\n");
|
||||
rrc->security.integrity_algorithms[0] = 0; /* nia0 = no integrity */
|
||||
rrc->security.integrity_algorithms_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
||||
|
||||
int num_gnbs = 0;
|
||||
@@ -679,7 +776,7 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
||||
}//End for (k=0; k <num_gnbs ; k++)
|
||||
}//End if (num_gnbs>0)
|
||||
|
||||
|
||||
config_security(rrc);
|
||||
}//End RCconfig_NRRRC function
|
||||
|
||||
int RCconfig_nr_gtpu(void ) {
|
||||
|
||||
@@ -452,4 +452,27 @@ typedef enum {
|
||||
#define CONFIG_HLP_WORKER "coding and FEP worker thread WORKER_DISABLE or WORKER_ENABLE\n"
|
||||
#define CONFIG_HLP_PARALLEL "PARALLEL_SINGLE_THREAD, PARALLEL_RU_L1_SPLIT, or PARALLEL_RU_L1_TRX_SPLIT(RU_L1_TRX_SPLIT by defult)\n"
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* security configuration */
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define CONFIG_STRING_SECURITY "security"
|
||||
|
||||
#define SECURITY_CONFIG_CIPHERING "ciphering_algorithms"
|
||||
#define SECURITY_CONFIG_INTEGRITY "integrity_algorithms"
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* security configuration */
|
||||
/* optname help paramflags XXXptr defXXXval type numelt */
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define SECURITY_GLOBALPARAMS_DESC { \
|
||||
{SECURITY_CONFIG_CIPHERING, "preferred ciphering algorithms\n", 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST, 0}, \
|
||||
{SECURITY_CONFIG_INTEGRITY, "preferred integrity algorithms\n", 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST, 0}, \
|
||||
}
|
||||
|
||||
#define SECURITY_CONFIG_CIPHERING_IDX 0
|
||||
#define SECURITY_CONFIG_INTEGRITY_IDX 1
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
||||
@@ -401,21 +401,37 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
||||
const int UE_id = add_new_nr_ue(Mod_idP, rnti, secondaryCellGroup);
|
||||
LOG_I(PHY,"Added new UE_id %d/%x with initial secondaryCellGroup\n",UE_id,rnti);
|
||||
} else if (add_ue == 1 && !get_softmodem_params()->phy_test) {
|
||||
/* TODO: should check for free RA process */
|
||||
const int CC_id = 0;
|
||||
NR_RA_t *ra = &RC.nrmac[Mod_idP]->common_channels[CC_id].ra[0];
|
||||
ra->state = RA_IDLE;
|
||||
NR_COMMON_channels_t *cc = &RC.nrmac[Mod_idP]->common_channels[CC_id];
|
||||
uint8_t ra_index = 0;
|
||||
/* checking for free RA process */
|
||||
for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) {
|
||||
if((cc->ra[ra_index].state == RA_IDLE) && (!cc->ra[ra_index].cfra)) break;
|
||||
}
|
||||
if (ra_index == NR_NB_RA_PROC_MAX) {
|
||||
LOG_E(MAC, "%s() %s:%d RA processes are not available for CFRA RNTI :%x\n", __FUNCTION__, __FILE__, __LINE__, rnti);
|
||||
return -1;
|
||||
}
|
||||
NR_RA_t *ra = &cc->ra[ra_index];
|
||||
ra->secondaryCellGroup = secondaryCellGroup;
|
||||
if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated!=NULL) {
|
||||
if (secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) {
|
||||
ra->cfra = true;
|
||||
ra->rnti = rnti;
|
||||
struct NR_CFRA cfra = *secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
|
||||
uint8_t num_preamble = cfra.resources.choice.ssb->ssb_ResourceList.list.count;
|
||||
struct NR_CFRA *cfra = secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
|
||||
uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count;
|
||||
ra->preambles.num_preambles = num_preamble;
|
||||
ra->preambles.preamble_list = (uint8_t *) malloc(num_preamble*sizeof(uint8_t));
|
||||
for (int i = 0; i < num_preamble; i++)
|
||||
ra->preambles.preamble_list[i] = cfra.resources.choice.ssb->ssb_ResourceList.list.array[i]->ra_PreambleIndex;
|
||||
for(int i=0; i<cc->num_active_ssb; i++) {
|
||||
for(int j=0; j<num_preamble; j++) {
|
||||
if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) {
|
||||
// one dedicated preamble for each beam
|
||||
ra->preambles.preamble_list[i] =
|
||||
cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ra_PreambleIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ra->cfra = false;
|
||||
|
||||
@@ -151,6 +151,38 @@ void find_SSB_and_RO_available(module_id_t module_idP) {
|
||||
uint8_t num_active_ssb = 0;
|
||||
uint8_t max_association_period = 1;
|
||||
|
||||
struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB;
|
||||
|
||||
switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present){
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
|
||||
cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
|
||||
break;
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
|
||||
cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
|
||||
break;
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
|
||||
cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
|
||||
break;
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
|
||||
cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
|
||||
break;
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
|
||||
cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
|
||||
break;
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
|
||||
cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
|
||||
break;
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
|
||||
cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
|
||||
break;
|
||||
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
|
||||
cc->cb_preambles_per_ssb = ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present);
|
||||
break;
|
||||
}
|
||||
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
|
||||
mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
|
||||
else
|
||||
@@ -181,25 +213,28 @@ void find_SSB_and_RO_available(module_id_t module_idP) {
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 1; (1 << (i-1)) <= max_association_period;i++) {
|
||||
cc->total_prach_occasions_per_config_period = total_RA_occasions;
|
||||
for(int i=1; (1 << (i-1)) < max_association_period; i++) {
|
||||
cc->max_association_period = (1 <<(i-1));
|
||||
total_RA_occasions = total_RA_occasions * cc->max_association_period;
|
||||
if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) {
|
||||
repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
total_RA_occasions = total_RA_occasions * i;
|
||||
cc->max_association_period = i;
|
||||
}
|
||||
}
|
||||
if(cc->max_association_period == 0)
|
||||
cc->max_association_period = 1;
|
||||
|
||||
unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO);
|
||||
cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion;
|
||||
cc->num_active_ssb = num_active_ssb;
|
||||
|
||||
LOG_I(MAC, "Total available RO %d, num of active SSB %d: unused RO = %d max_association_period %u N_RA_sfn %u \n",
|
||||
cc->total_prach_occasions, cc->num_active_ssb, unused_RA_occasion, max_association_period, N_RA_sfn);
|
||||
LOG_I(MAC,
|
||||
"Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u total_prach_occasions_per_config_period %u\n",
|
||||
cc->total_prach_occasions,
|
||||
cc->num_active_ssb,
|
||||
unused_RA_occasion,
|
||||
cc->max_association_period,
|
||||
N_RA_sfn,
|
||||
cc->total_prach_occasions_per_config_period);
|
||||
}
|
||||
|
||||
void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
||||
@@ -439,145 +474,167 @@ void nr_initiate_ra_proc(module_id_t module_idP,
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_RA_t *ra = &cc->ra[0];
|
||||
|
||||
uint16_t ra_rnti;
|
||||
uint8_t total_RApreambles = 64;
|
||||
uint8_t num_ssb_per_RO = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
|
||||
int pr_found;
|
||||
|
||||
// ra_rnti from 5.1.3 in 38.321
|
||||
// FK: in case of long PRACH the phone seems to expect the subframe number instead of the slot number here.
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present==NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l839)
|
||||
ra_rnti=1+symbol+(9/*slotP*/*14)+(freq_index*14*80)+(ul_carrier_id*14*80*8);
|
||||
else
|
||||
ra_rnti=1+symbol+(slotP*14)+(freq_index*14*80)+(ul_carrier_id*14*80*8);
|
||||
if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
|
||||
total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;
|
||||
|
||||
|
||||
// if the preamble received correspond to one of the listed
|
||||
// the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries
|
||||
int pr_found=0;
|
||||
for (int i = 0; i < ra->preambles.num_preambles; i++) {
|
||||
if (preamble_index == ra->preambles.preamble_list[i]) {
|
||||
pr_found=1;
|
||||
break;
|
||||
}
|
||||
if(num_ssb_per_RO > 3) { /*num of ssb per RO >= 1*/
|
||||
num_ssb_per_RO -= 3;
|
||||
total_RApreambles = total_RApreambles/num_ssb_per_RO ;
|
||||
}
|
||||
|
||||
if (!pr_found) {
|
||||
LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n",
|
||||
module_idP, preamble_index);
|
||||
|
||||
return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
|
||||
}
|
||||
// This should be handled differently when we use the initialBWP for RA
|
||||
ra->bwp_id=1;
|
||||
NR_BWP_Downlink_t *bwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1);
|
||||
|
||||
LOG_I(MAC, "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d Initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, slotP, preamble_index);
|
||||
|
||||
if (ra->state == RA_IDLE) {
|
||||
|
||||
uint8_t beam_index = ssb_index_from_prach(module_idP,
|
||||
frameP,
|
||||
slotP,
|
||||
preamble_index,
|
||||
freq_index,
|
||||
symbol);
|
||||
|
||||
LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP);
|
||||
ra->state = Msg2;
|
||||
ra->timing_offset = timing_offset;
|
||||
ra->preamble_slot = slotP;
|
||||
|
||||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||||
AssertFatal(commonSearchSpaceList->list.count>0,
|
||||
"common SearchSpace list has 0 elements\n");
|
||||
// Common searchspace list
|
||||
for (int i=0;i<commonSearchSpaceList->list.count;i++) {
|
||||
ss=commonSearchSpaceList->list.array[i];
|
||||
if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)
|
||||
ra->ra_ss=ss;
|
||||
}
|
||||
|
||||
// retrieving ra pdcch monitoring period and offset
|
||||
find_monitoring_periodicity_offset_common(ra->ra_ss,
|
||||
&monitoring_slot_period,
|
||||
&monitoring_offset);
|
||||
|
||||
nr_schedule_msg2(frameP, slotP, &msg2_frame, &msg2_slot, scc, monitoring_slot_period, monitoring_offset,beam_index,cc->num_active_ssb);
|
||||
|
||||
ra->Msg2_frame = msg2_frame;
|
||||
ra->Msg2_slot = msg2_slot;
|
||||
|
||||
LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
|
||||
|
||||
// TODO: Configure RRC with the new RNTI of the following commented lines
|
||||
/*
|
||||
int loop = 0;
|
||||
if (!ra->cfra) {
|
||||
do {
|
||||
ra->rnti = (taus() % 65518) + 1;
|
||||
loop++;
|
||||
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
NR_RA_t *ra = &cc->ra[i];
|
||||
pr_found = 0;
|
||||
if (ra->state == RA_IDLE) {
|
||||
for(int j = 0; j < ra->preambles.num_preambles; j++) {
|
||||
//check if the preamble received correspond to one of the listed or configured preambles
|
||||
if (preamble_index == ra->preambles.preamble_list[j]) {
|
||||
pr_found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (loop != 100 && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) && ra->rnti >= 1 && ra->rnti <= 65519));
|
||||
if (loop == 100) {
|
||||
LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
abort();
|
||||
|
||||
if (pr_found == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t ra_rnti;
|
||||
|
||||
// ra_rnti from 5.1.3 in 38.321
|
||||
// FK: in case of long PRACH the phone seems to expect the subframe number instead of the slot number here.
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present
|
||||
== NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l839)
|
||||
ra_rnti = 1 + symbol + (9 /*slotP*/ * 14) + (freq_index * 14 * 80) + (ul_carrier_id * 14 * 80 * 8);
|
||||
else
|
||||
ra_rnti = 1 + symbol + (slotP * 14) + (freq_index * 14 * 80) + (ul_carrier_id * 14 * 80 * 8);
|
||||
|
||||
// This should be handled differently when we use the initialBWP for RA
|
||||
ra->bwp_id = 1;
|
||||
NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList
|
||||
->list.array[ra->bwp_id - 1];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1);
|
||||
|
||||
LOG_I(MAC,
|
||||
"[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d Initiating RA procedure for preamble index %d\n",
|
||||
module_idP,
|
||||
CC_id,
|
||||
frameP,
|
||||
slotP,
|
||||
preamble_index);
|
||||
|
||||
uint8_t beam_index = ssb_index_from_prach(module_idP, frameP, slotP, preamble_index, freq_index, symbol);
|
||||
|
||||
// the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries
|
||||
if (ra->cfra) {
|
||||
// if the preamble received correspond to one of the listed
|
||||
if (!(preamble_index == ra->preambles.preamble_list[beam_index])) {
|
||||
LOG_E(
|
||||
MAC,
|
||||
"[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n",
|
||||
module_idP,
|
||||
preamble_index);
|
||||
continue; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
|
||||
}
|
||||
}
|
||||
int loop = 0;
|
||||
LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP);
|
||||
ra->state = Msg2;
|
||||
ra->timing_offset = timing_offset;
|
||||
ra->preamble_slot = slotP;
|
||||
|
||||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList =
|
||||
bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||||
AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n");
|
||||
// Common searchspace list
|
||||
for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
|
||||
ss = commonSearchSpaceList->list.array[i];
|
||||
if (ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)
|
||||
ra->ra_ss = ss;
|
||||
}
|
||||
|
||||
// retrieving ra pdcch monitoring period and offset
|
||||
find_monitoring_periodicity_offset_common(ra->ra_ss, &monitoring_slot_period, &monitoring_offset);
|
||||
|
||||
nr_schedule_msg2(frameP,
|
||||
slotP,
|
||||
&msg2_frame,
|
||||
&msg2_slot,
|
||||
scc,
|
||||
monitoring_slot_period,
|
||||
monitoring_offset,
|
||||
beam_index,
|
||||
cc->num_active_ssb);
|
||||
|
||||
ra->Msg2_frame = msg2_frame;
|
||||
ra->Msg2_slot = msg2_slot;
|
||||
|
||||
LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
|
||||
if (!ra->cfra) {
|
||||
do {
|
||||
ra->rnti = (taus() % 65518) + 1;
|
||||
loop++;
|
||||
} while (loop != 100
|
||||
&& !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1)
|
||||
&& ra->rnti >= 1 && ra->rnti <= 65519));
|
||||
if (loop == 100) {
|
||||
LOG_E(MAC, "%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
ra->RA_rnti = ra_rnti;
|
||||
ra->preamble_index = preamble_index;
|
||||
ra->beam_id = beam_index;
|
||||
|
||||
LOG_I(MAC,
|
||||
"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB "
|
||||
"index %u\n",
|
||||
module_idP,
|
||||
CC_id,
|
||||
frameP,
|
||||
ra->Msg2_frame,
|
||||
ra->Msg2_slot,
|
||||
ra->RA_rnti,
|
||||
cc->ssb_index[beam_index]);
|
||||
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
ra->RA_rnti = ra_rnti;
|
||||
ra->preamble_index = preamble_index;
|
||||
ra->beam_id = beam_index;
|
||||
|
||||
LOG_I(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB index %u\n",
|
||||
module_idP,
|
||||
CC_id,
|
||||
frameP,
|
||||
ra->Msg2_frame,
|
||||
ra->Msg2_slot,
|
||||
ra->RA_rnti,
|
||||
cc->ssb_index[beam_index]);
|
||||
|
||||
return;
|
||||
}
|
||||
LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0);
|
||||
}
|
||||
|
||||
void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
|
||||
|
||||
//uint8_t i = 0;
|
||||
int CC_id = 0;
|
||||
void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
||||
{
|
||||
gNB_MAC_INST *mac = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
|
||||
start_meas(&mac->schedule_ra);
|
||||
|
||||
// for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
// for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
|
||||
// NR_RA_t *ra = &cc->ra[i];
|
||||
NR_RA_t *ra = &cc->ra[0];
|
||||
|
||||
LOG_D(MAC,"RA[state:%d]\n",ra->state);
|
||||
switch (ra->state){
|
||||
case Msg2:
|
||||
nr_generate_Msg2(module_idP, CC_id, frameP, slotP);
|
||||
break;
|
||||
case Msg4:
|
||||
nr_generate_Msg4(module_idP, CC_id, frameP, slotP);
|
||||
break;
|
||||
case WAIT_Msg4_ACK:
|
||||
nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
|
||||
NR_RA_t *ra = &cc->ra[i];
|
||||
LOG_D(MAC, "RA[state:%d]\n", ra->state);
|
||||
switch (ra->state) {
|
||||
case Msg2:
|
||||
nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra);
|
||||
break;
|
||||
case Msg4:
|
||||
nr_generate_Msg4(module_idP, CC_id, frameP, slotP);
|
||||
break;
|
||||
case WAIT_Msg4_ACK:
|
||||
nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
stop_meas(&mac->schedule_ra);
|
||||
}
|
||||
|
||||
@@ -640,12 +697,11 @@ void nr_get_Msg3alloc(module_id_t module_id,
|
||||
ra->msg3_first_rb = rbStart;
|
||||
}
|
||||
|
||||
void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){
|
||||
|
||||
void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu)
|
||||
{
|
||||
gNB_MAC_INST *mac = RC.nrmac[module_idP];
|
||||
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_RA_t *ra = &cc->ra[0];
|
||||
|
||||
if (ra->state == RA_IDLE) {
|
||||
LOG_W(MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti);
|
||||
@@ -760,18 +816,10 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t
|
||||
pusch_pdu->nrOfLayers = 1)>>3;
|
||||
|
||||
// calling function to fill rar message
|
||||
nr_fill_rar(module_idP, ra, cc->RAR_pdu.payload, pusch_pdu);
|
||||
|
||||
nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu);
|
||||
}
|
||||
|
||||
// WIP
|
||||
// todo:
|
||||
// - fix me
|
||||
// - get msg3 alloc (see nr_process_rar)
|
||||
void nr_generate_Msg2(module_id_t module_idP,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP)
|
||||
void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra)
|
||||
{
|
||||
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
|
||||
@@ -975,6 +1023,7 @@ void nr_generate_Msg2(module_id_t module_idP,
|
||||
nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_payload.tb_scaling);
|
||||
|
||||
// DL TX request
|
||||
nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];
|
||||
tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0];
|
||||
tx_req->PDU_index = pduindex;
|
||||
tx_req->num_TLV = 1;
|
||||
|
||||
@@ -245,7 +245,9 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
|
||||
TX_req->PDU_index = nr_mac->pdu_index[CC_id]++;
|
||||
TX_req->num_TLV = 1;
|
||||
TX_req->TLVs[0].length = 8;
|
||||
memcpy((void*)&TX_req->TLVs[0].value.direct[0],(void*)&cc[CC_id].RAR_pdu.payload[0],TX_req->TLVs[0].length);
|
||||
// why do we copy from RAR_pdu here? Shouldn't we fill some more or less
|
||||
// meaningful data, e.g., padding + random data?
|
||||
//memcpy((void *)&TX_req->TLVs[0].value.direct[0], (void *)&cc[CC_id].RAR_pdu[0].payload[0], TX_req->TLVs[0].length);
|
||||
nr_mac->TX_req[CC_id].Number_of_PDUs++;
|
||||
nr_mac->TX_req[CC_id].SFN=frameP;
|
||||
nr_mac->TX_req[CC_id].Slot=slotP;
|
||||
|
||||
@@ -432,7 +432,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
if (sduP != NULL){
|
||||
LOG_D(NR_MAC, "Received PDU at MAC gNB \n");
|
||||
|
||||
UE_scheduling_control->sched_ul_bytes -= UE_info->mac_stats[UE_id].ulsch_current_bytes;
|
||||
const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
|
||||
UE_scheduling_control->sched_ul_bytes -= tb_size;
|
||||
if (UE_scheduling_control->sched_ul_bytes < 0)
|
||||
UE_scheduling_control->sched_ul_bytes = 0;
|
||||
|
||||
@@ -442,7 +443,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
|
||||
/* reduce sched_ul_bytes when cur_harq->round == 3 */
|
||||
if (cur_harq->round == 3){
|
||||
UE_scheduling_control->sched_ul_bytes -= UE_info->mac_stats[UE_id].ulsch_current_bytes;
|
||||
const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
|
||||
UE_scheduling_control->sched_ul_bytes -= tb_size;
|
||||
if (UE_scheduling_control->sched_ul_bytes < 0)
|
||||
UE_scheduling_control->sched_ul_bytes = 0;
|
||||
}
|
||||
@@ -867,7 +869,7 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
/* a PDCCH PDU groups DCIs per BWP and CORESET. Save a pointer to each
|
||||
* allocated PDCCH so we can easily allocate UE's DCIs independent of any
|
||||
* CORESET order */
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {0};
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_bwp_coreset[MAX_NUM_BWP][MAX_NUM_CORESET] = {{0}};
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
@@ -921,6 +923,7 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
/* Save information on MCS, TBS etc for the current initial transmission
|
||||
* so we have access to it when retransmitting */
|
||||
cur_harq->sched_pusch = *sched_pusch;
|
||||
sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
|
||||
} else {
|
||||
LOG_D(MAC,
|
||||
"%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n",
|
||||
@@ -934,7 +937,6 @@ void nr_schedule_ulsch(module_id_t module_id,
|
||||
cur_harq->ndi);
|
||||
}
|
||||
UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
|
||||
sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
|
||||
|
||||
LOG_D(MAC,
|
||||
"%4d.%2d RNTI %04x UL sched %4d.%2d start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
|
||||
|
||||
@@ -353,10 +353,7 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
|
||||
unsigned char drx_cmd,
|
||||
unsigned char *ue_cont_res_id);
|
||||
|
||||
void nr_generate_Msg2(module_id_t module_idP,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t slotP);
|
||||
void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra);
|
||||
|
||||
void nr_generate_Msg4(module_id_t module_idP,
|
||||
int CC_id,
|
||||
|
||||
@@ -194,8 +194,6 @@ typedef struct {
|
||||
uint32_t PCCH_alloc_pdu;
|
||||
/// Outgoing PCCH pdu for PHY
|
||||
PCCH_PDU PCCH_pdu;
|
||||
/// Outgoing RAR pdu for PHY
|
||||
RAR_PDU RAR_pdu;
|
||||
/// Template for RA computations
|
||||
NR_RA_t ra[NR_NB_RA_PROC_MAX];
|
||||
/// VRB map for common channels
|
||||
@@ -215,6 +213,8 @@ typedef struct {
|
||||
uint8_t max_association_period;
|
||||
//SSB index
|
||||
uint8_t ssb_index[MAX_NUM_OF_SSB];
|
||||
//CB preambles for each SSB
|
||||
uint8_t cb_preambles_per_ssb;
|
||||
} NR_COMMON_channels_t;
|
||||
|
||||
|
||||
|
||||
@@ -22,11 +22,12 @@
|
||||
#include "nr_pdcp_entity.h"
|
||||
|
||||
#include "nr_pdcp_entity_drb_am.h"
|
||||
#include "nr_pdcp_security_nea2.h"
|
||||
|
||||
#include "LOG/log.h"
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
|
||||
int rb_id,
|
||||
int is_gnb, int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
@@ -38,7 +39,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
|
||||
}
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
int rb_id,
|
||||
int is_gnb, int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
@@ -47,7 +48,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
void *deliver_pdu_data,
|
||||
int sn_size,
|
||||
int t_reordering,
|
||||
int discard_timer)
|
||||
int discard_timer,
|
||||
int ciphering_algorithm,
|
||||
int integrity_algorithm,
|
||||
unsigned char *ciphering_key,
|
||||
unsigned char *integrity_key)
|
||||
{
|
||||
nr_pdcp_entity_drb_am_t *ret;
|
||||
|
||||
@@ -76,5 +81,25 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
|
||||
ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1;
|
||||
|
||||
if (ciphering_key != NULL && ciphering_algorithm != 0) {
|
||||
if (ciphering_algorithm != 2) {
|
||||
LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n");
|
||||
exit(1);
|
||||
}
|
||||
ret->common.has_ciphering = 1;
|
||||
ret->common.ciphering_algorithm = ciphering_algorithm;
|
||||
memcpy(ret->common.ciphering_key, ciphering_key, 16);
|
||||
|
||||
ret->common.security_context = nr_pdcp_security_nea2_init(ciphering_key);
|
||||
ret->common.cipher = nr_pdcp_security_nea2_cipher;
|
||||
ret->common.free_security = nr_pdcp_security_nea2_free_security;
|
||||
}
|
||||
ret->common.is_gnb = is_gnb;
|
||||
|
||||
if (integrity_key != NULL) {
|
||||
printf("%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (nr_pdcp_entity_t *)ret;
|
||||
}
|
||||
|
||||
@@ -42,10 +42,28 @@ typedef struct nr_pdcp_entity_t {
|
||||
int tx_hfn;
|
||||
int next_nr_pdcp_tx_sn;
|
||||
int maximum_nr_pdcp_sn;
|
||||
|
||||
/* security */
|
||||
int has_ciphering;
|
||||
int has_integrity;
|
||||
int ciphering_algorithm;
|
||||
int integrity_algorithm;
|
||||
unsigned char ciphering_key[16];
|
||||
unsigned char integrity_key[16];
|
||||
void *security_context;
|
||||
void (*cipher)(void *security_context,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction);
|
||||
void (*free_security)(void *security_context);
|
||||
/* security algorithms need to know uplink/downlink information
|
||||
* which is reverse for gnb and ue, so we need to know if this
|
||||
* pdcp entity is for a gnb or an ue
|
||||
*/
|
||||
int is_gnb;
|
||||
} nr_pdcp_entity_t;
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
|
||||
int rb_id,
|
||||
int is_gnb, int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
@@ -54,7 +72,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_srb(
|
||||
void *deliver_pdu_data);
|
||||
|
||||
nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
int rb_id,
|
||||
int is_gnb, int rb_id,
|
||||
void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity,
|
||||
char *buf, int size),
|
||||
void *deliver_sdu_data,
|
||||
@@ -63,7 +81,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am(
|
||||
void *deliver_pdu_data,
|
||||
int sn_size,
|
||||
int t_reordering,
|
||||
int discard_timer);
|
||||
int discard_timer,
|
||||
int ciphering_algorithm,
|
||||
int integrity_algorithm,
|
||||
unsigned char *ciphering_key,
|
||||
unsigned char *integrity_key);
|
||||
|
||||
void nr_DRB_preconfiguration(uint16_t crnti);
|
||||
|
||||
|
||||
@@ -29,12 +29,21 @@
|
||||
void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size)
|
||||
{
|
||||
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
|
||||
int sn;
|
||||
|
||||
if (size < 3) abort();
|
||||
|
||||
if (!(buffer[0] & 0x80))
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
|
||||
sn = (((unsigned char)buffer[0] & 0x3) << 16) |
|
||||
((unsigned char)buffer[1] << 8) |
|
||||
(unsigned char)buffer[2];
|
||||
|
||||
if (entity->common.has_ciphering)
|
||||
entity->common.cipher(entity->common.security_context, (unsigned char *)buffer+3, size-3,
|
||||
entity->rb_id, sn, entity->common.is_gnb ? 0 : 1);
|
||||
|
||||
entity->common.deliver_sdu(entity->common.deliver_sdu_data,
|
||||
(nr_pdcp_entity_t *)entity, buffer+3, size-3);
|
||||
}
|
||||
@@ -59,6 +68,10 @@ void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int
|
||||
buf[2] = sn & 0xff;
|
||||
memcpy(buf+3, buffer, size);
|
||||
|
||||
if (entity->common.has_ciphering)
|
||||
entity->common.cipher(entity->common.security_context, (unsigned char *)buf+3, size,
|
||||
entity->rb_id, sn, entity->common.is_gnb ? 1 : 0);
|
||||
|
||||
entity->common.deliver_pdu(entity->common.deliver_pdu_data,
|
||||
(nr_pdcp_entity_t *)entity, buf, size+3, sdu_id);
|
||||
}
|
||||
@@ -71,5 +84,7 @@ void nr_pdcp_entity_drb_am_set_integrity_key(nr_pdcp_entity_t *_entity, char *ke
|
||||
void nr_pdcp_entity_drb_am_delete(nr_pdcp_entity_t *_entity)
|
||||
{
|
||||
nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity;
|
||||
if (entity->common.free_security != NULL)
|
||||
entity->common.free_security(entity->common.security_context);
|
||||
free(entity);
|
||||
}
|
||||
|
||||
@@ -591,7 +591,11 @@ static void add_srb(int rnti, struct NR_SRB_ToAddMod *s)
|
||||
TODO;
|
||||
}
|
||||
|
||||
static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s)
|
||||
static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
|
||||
int ciphering_algorithm,
|
||||
int integrity_algorithm,
|
||||
unsigned char *ciphering_key,
|
||||
unsigned char *integrity_key)
|
||||
{
|
||||
nr_pdcp_entity_t *pdcp_drb;
|
||||
nr_pdcp_ue_t *ue;
|
||||
@@ -621,8 +625,11 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s)
|
||||
LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n",
|
||||
__FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
} else {
|
||||
pdcp_drb = new_nr_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue,
|
||||
sn_size_dl, t_reordering, discard_timer);
|
||||
pdcp_drb = new_nr_pdcp_entity_drb_am(is_gnb, drb_id,
|
||||
deliver_sdu_drb, ue, deliver_pdu_drb, ue,
|
||||
sn_size_dl, t_reordering, discard_timer,
|
||||
ciphering_algorithm, integrity_algorithm,
|
||||
ciphering_key, integrity_key);
|
||||
nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb);
|
||||
|
||||
LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti);
|
||||
@@ -630,16 +637,23 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s)
|
||||
nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
|
||||
}
|
||||
|
||||
static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_Config_t *rlc_Config)
|
||||
static void add_drb(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s,
|
||||
NR_RLC_Config_t *rlc_Config,
|
||||
int ciphering_algorithm,
|
||||
int integrity_algorithm,
|
||||
unsigned char *ciphering_key,
|
||||
unsigned char *integrity_key)
|
||||
{
|
||||
switch (rlc_Config->present) {
|
||||
case NR_RLC_Config_PR_am:
|
||||
add_drb_am(rnti, s);
|
||||
add_drb_am(is_gnb, rnti, s, ciphering_algorithm, integrity_algorithm,
|
||||
ciphering_key, integrity_key);
|
||||
break;
|
||||
case NR_RLC_Config_PR_um_Bi_Directional:
|
||||
//add_drb_um(rnti, s);
|
||||
/* hack */
|
||||
add_drb_am(rnti, s);
|
||||
add_drb_am(is_gnb, rnti, s, ciphering_algorithm, integrity_algorithm,
|
||||
ciphering_key, integrity_key);
|
||||
break;
|
||||
default:
|
||||
LOG_E(PDCP, "%s:%d:%s: fatal: unhandled DRB type\n",
|
||||
@@ -657,7 +671,8 @@ boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
const uint8_t security_modeP,
|
||||
uint8_t *const kRRCenc,
|
||||
uint8_t *const kRRCint,
|
||||
uint8_t *const kUPenc
|
||||
uint8_t *const kUPenc,
|
||||
uint8_t *const kUPint
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
|
||||
#endif
|
||||
@@ -676,7 +691,7 @@ boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
//srb2add_list == NULL ||
|
||||
//drb2add_list != NULL ||
|
||||
drb2release_list != NULL ||
|
||||
security_modeP != 255 ||
|
||||
//security_modeP != 255 ||
|
||||
//kRRCenc != NULL ||
|
||||
//kRRCint != NULL ||
|
||||
//kUPenc != NULL ||
|
||||
@@ -693,7 +708,10 @@ boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
|
||||
if (drb2add_list != NULL) {
|
||||
for (i = 0; i < drb2add_list->list.count; i++) {
|
||||
add_drb(rnti, drb2add_list->list.array[i], rlc_bearer2add_list->list.array[i]->rlc_Config);
|
||||
add_drb(ctxt_pP->enb_flag, rnti, drb2add_list->list.array[i],
|
||||
rlc_bearer2add_list->list.array[i]->rlc_Config,
|
||||
security_modeP & 0x0f, (security_modeP >> 4) & 0x0f,
|
||||
kUPenc, kUPint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -705,6 +723,7 @@ boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
free(kRRCenc);
|
||||
free(kRRCint);
|
||||
free(kUPenc);
|
||||
free(kUPint);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -805,6 +824,7 @@ void nr_DRB_preconfiguration(uint16_t crnti)
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
Rlc_Bearer_ToAdd_list);
|
||||
|
||||
nr_rrc_rlc_config_asn1_req (&ctxt,
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "nr_pdcp_security_nea2.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <nettle/nettle-meta.h>
|
||||
#include <nettle/aes.h>
|
||||
#include <nettle/ctr.h>
|
||||
|
||||
void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key)
|
||||
{
|
||||
void *ctx = calloc(1, nettle_aes128.context_size);
|
||||
if (ctx == NULL) exit(1);
|
||||
|
||||
#if NETTLE_VERSION_MAJOR < 3
|
||||
nettle_aes128.set_encrypt_key(ctx, 16, ciphering_key);
|
||||
#else
|
||||
nettle_aes128.set_encrypt_key(ctx, ciphering_key);
|
||||
#endif
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void nr_pdcp_security_nea2_cipher(void *security_context,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction)
|
||||
{
|
||||
unsigned char t[16];
|
||||
|
||||
t[0] = (count >> 24) & 255;
|
||||
t[1] = (count >> 16) & 255;
|
||||
t[2] = (count >> 8) & 255;
|
||||
t[3] = (count ) & 255;
|
||||
t[4] = ((bearer-1) << 3) | (direction << 2);
|
||||
memset(&t[5], 0, 16-5);
|
||||
|
||||
nettle_ctr_crypt(security_context, nettle_aes128.encrypt,
|
||||
nettle_aes128.block_size, t,
|
||||
length, buffer, buffer);
|
||||
}
|
||||
|
||||
void nr_pdcp_security_nea2_free_security(void *security_context)
|
||||
{
|
||||
free(security_context);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef _NR_PDCP_SECURITY_NEA2_H_
|
||||
#define _NR_PDCP_SECURITY_NEA2_H_
|
||||
|
||||
void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key);
|
||||
|
||||
void nr_pdcp_security_nea2_cipher(void *security_context,
|
||||
unsigned char *buffer, int length,
|
||||
int bearer, int count, int direction);
|
||||
|
||||
void nr_pdcp_security_nea2_free_security(void *security_context);
|
||||
|
||||
#endif /* _NR_PDCP_SECURITY_NEA2_H_ */
|
||||
@@ -546,6 +546,13 @@ typedef struct rrc_gummei_s {
|
||||
uint16_t mme_group_id;
|
||||
} rrc_gummei_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t ciphering_algorithms;
|
||||
uint16_t integrity_algorithms;
|
||||
uint16_t sk_counter;
|
||||
uint8_t kgNB[32];
|
||||
} lte_rrc_nr_security_t;
|
||||
|
||||
typedef struct eNB_RRC_UE_s {
|
||||
uint8_t primaryCC_id;
|
||||
LTE_SCellToAddMod_r10_t sCell_config[2];
|
||||
@@ -615,6 +622,9 @@ typedef struct eNB_RRC_UE_s {
|
||||
|
||||
security_capabilities_t security_capabilities;
|
||||
|
||||
/* security capabilities and settings for an UE in ENDC mode */
|
||||
lte_rrc_nr_security_t nr_security;
|
||||
|
||||
int next_hop_chain_count;
|
||||
|
||||
uint8_t next_security_key[SECURITY_KEY_LENGTH];
|
||||
|
||||
@@ -4426,69 +4426,11 @@ static int encode_CG_ConfigInfo(
|
||||
struct NR_RadioBearerConfig *rb_config = NULL;
|
||||
asn_enc_rval_t enc_rval;
|
||||
int RRC_OK = 1;
|
||||
int index = 0;
|
||||
char temp_buff[ASN_MAX_ENCODE_SIZE];
|
||||
NR_UE_CapabilityRAT_ContainerList_t *ue_cap_rat_container_list = NULL;
|
||||
NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container_MRDC = NULL;
|
||||
NR_UE_CapabilityRAT_Container_t *ue_cap_rat_container_nr = NULL;
|
||||
int RAT_Container_count = 0;
|
||||
rb_config = calloc(1,sizeof(struct NR_RadioBearerConfig));
|
||||
AssertFatal(rb_config != NULL,"failed to allocate memory for rb_config");
|
||||
|
||||
if(ue_context_pP->ue_context.DRB_configList->list.count != 0) {
|
||||
rb_config->drb_ToAddModList = calloc(1,sizeof(struct NR_DRB_ToAddModList ));
|
||||
AssertFatal(rb_config->drb_ToAddModList != NULL,"failed to allocated memory for drbtoaddmodlist");
|
||||
rb_config->drb_ToAddModList->list.count = NUMBEROF_DRBS_TOBE_ADDED;
|
||||
rb_config->drb_ToAddModList->list.array
|
||||
= calloc(NUMBEROF_DRBS_TOBE_ADDED, sizeof(struct NR_DRB_ToAddMod *));
|
||||
AssertFatal( rb_config->drb_ToAddModList->list.array != NULL,
|
||||
"falied to allocate memory for list.array");
|
||||
|
||||
for(index = 0; index < NUMBEROF_DRBS_TOBE_ADDED; index++) {
|
||||
rb_config->drb_ToAddModList->list.array[index]
|
||||
= calloc(1,sizeof(struct NR_DRB_ToAddMod));
|
||||
AssertFatal(rb_config->drb_ToAddModList->list.array[index] != NULL,
|
||||
"failed to allocate memory for drb_toaddmod");
|
||||
rb_config->drb_ToAddModList->list.array[index]->drb_Identity
|
||||
= ue_context_pP->ue_context.DRB_configList->list.array[index]->drb_Identity;
|
||||
|
||||
if(ue_context_pP->ue_context.DRB_configList->list.array[index]->eps_BearerIdentity) {
|
||||
rb_config->drb_ToAddModList->list.array[index]->cnAssociation
|
||||
= calloc(1,sizeof(struct NR_DRB_ToAddMod__cnAssociation));
|
||||
AssertFatal(rb_config->drb_ToAddModList->list.array[index]->cnAssociation != NULL,
|
||||
"failed to allocate memory cnAssociation");
|
||||
rb_config->drb_ToAddModList->list.array[index]->cnAssociation->present
|
||||
= NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity;
|
||||
rb_config->drb_ToAddModList->list.array[index]->cnAssociation->choice.eps_BearerIdentity
|
||||
= *(ue_context_pP->ue_context.DRB_configList->list.array[index]->eps_BearerIdentity);
|
||||
}
|
||||
|
||||
rb_config->drb_ToAddModList->list.array[index]->pdcp_Config = calloc(1,sizeof(struct NR_PDCP_Config));
|
||||
rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb = calloc(1,sizeof(struct NR_PDCP_Config__drb));
|
||||
rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->discardTimer = calloc(1,sizeof(long));
|
||||
*rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->discardTimer
|
||||
= *(ue_context_pP->ue_context.DRB_configList->list.array[index]->pdcp_Config->discardTimer);
|
||||
rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(long));
|
||||
*rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeUL
|
||||
= NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits;
|
||||
rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(long));
|
||||
*rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->pdcp_SN_SizeDL
|
||||
= NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits;
|
||||
rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->headerCompression.present
|
||||
= NR_PDCP_Config__drb__headerCompression_PR_notUsed;
|
||||
rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->drb->headerCompression.choice.notUsed = 0;
|
||||
rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->t_Reordering = calloc(1,sizeof(long));
|
||||
*rb_config->drb_ToAddModList->list.array[index]->pdcp_Config->t_Reordering
|
||||
= NR_PDCP_Config__t_Reordering_ms0;
|
||||
}
|
||||
|
||||
rb_config->securityConfig = calloc(1,sizeof(struct NR_SecurityConfig ));
|
||||
rb_config->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(struct NR_SecurityAlgorithmConfig));
|
||||
rb_config->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0;
|
||||
rb_config->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm = NULL;
|
||||
rb_config->securityConfig->keyToUse = calloc(1,sizeof(long));
|
||||
*rb_config->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master;
|
||||
}
|
||||
|
||||
cg_configinfo = calloc(1,sizeof(struct NR_CG_ConfigInfo));
|
||||
AssertFatal(cg_configinfo != NULL,"failed to allocate memory for cg_configinfo");
|
||||
@@ -4548,15 +4490,6 @@ static int encode_CG_ConfigInfo(
|
||||
(const char *)temp_buff, (enc_rval.encoded+7)>>3);
|
||||
}
|
||||
|
||||
cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->mcg_RB_Config
|
||||
= calloc(1,sizeof(OCTET_STRING_t));
|
||||
AssertFatal(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->
|
||||
mcg_RB_Config != NULL, "failed to allocate memory for mcg_rb_config");
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig,NULL,(void *)rb_config,temp_buff,ASN_MAX_ENCODE_SIZE);
|
||||
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
|
||||
enc_rval.failed_type->name, enc_rval.encoded);
|
||||
OCTET_STRING_fromBuf(cg_configinfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo->mcg_RB_Config,
|
||||
(const char *)temp_buff, (enc_rval.encoded+7)>>3);
|
||||
// this xer_fprint can be enabled for additional debugging messages
|
||||
// xer_fprint(stdout,&asn_DEF_NR_CG_ConfigInfo,(void *)cg_configinfo);
|
||||
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo,NULL,(void *)cg_configinfo,
|
||||
@@ -4665,11 +4598,20 @@ rrc_eNB_process_MeasurementReport(
|
||||
|
||||
msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ);
|
||||
memset(&(X2AP_ENDC_SGNB_ADDITION_REQ(msg)), 0, sizeof(x2ap_ENDC_sgnb_addition_req_t));
|
||||
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).rnti = ctxt_pP->rnti;
|
||||
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.encryption_algorithms = ue_context_pP->ue_context.nr_security.ciphering_algorithms;
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.integrity_algorithms = ue_context_pP->ue_context.nr_security.integrity_algorithms;
|
||||
|
||||
memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).kgnb, ue_context_pP->ue_context.nr_security.kgNB, 32);
|
||||
|
||||
memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer,enc_buf,enc_size);
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer_size = enc_size;
|
||||
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).target_physCellId
|
||||
= measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[0]->physCellId;
|
||||
|
||||
//For the moment we have a single E-RAB which will be the one to be added to the gNB
|
||||
//Not sure how to select bearers to be added if there are multiple.
|
||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).nb_e_rabs_tobeadded = 1;
|
||||
|
||||
@@ -1045,6 +1045,15 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
|
||||
}
|
||||
}
|
||||
|
||||
ue_context_p->ue_context.nr_security.ciphering_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.encryption_algorithms;
|
||||
ue_context_p->ue_context.nr_security.integrity_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.integrity_algorithms;
|
||||
/* let's initialize sk_counter to 0 */
|
||||
ue_context_p->ue_context.nr_security.sk_counter = 0;
|
||||
/* let's compute kgNB */
|
||||
derive_skgNB(ue_context_p->ue_context.kenb,
|
||||
ue_context_p->ue_context.nr_security.sk_counter,
|
||||
ue_context_p->ue_context.nr_security.kgNB);
|
||||
|
||||
// in case, send the S1SP initial context response if it is not sent with the attach complete message
|
||||
if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) {
|
||||
LOG_I(RRC, "Sending rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", ue_context_p->ue_context.reestablishment_cause);
|
||||
|
||||
@@ -447,6 +447,15 @@ typedef struct {
|
||||
//---------------------------------------------------
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* nea0 = 0, nea1 = 1, ... */
|
||||
int ciphering_algorithms[4];
|
||||
int ciphering_algorithms_count;
|
||||
|
||||
/* nia0 = 0, nia1 = 1, ... */
|
||||
int integrity_algorithms[4];
|
||||
int integrity_algorithms_count;
|
||||
} nr_security_configuration_t;
|
||||
|
||||
//---NR---(completely change)---------------------
|
||||
typedef struct gNB_RRC_INST_s {
|
||||
@@ -479,6 +488,8 @@ typedef struct gNB_RRC_INST_s {
|
||||
int srb1_timer_status_prohibit;
|
||||
int srs_enable[MAX_NUM_CCs];
|
||||
|
||||
// security configuration (preferred algorithms)
|
||||
nr_security_configuration_t security;
|
||||
} gNB_RRC_INST;
|
||||
|
||||
#include "nr_rrc_proto.h" //should be put here otherwise compilation error
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "LTE_UE-CapabilityRAT-ContainerList.h"
|
||||
#include "NR_CG-Config.h"
|
||||
#include "NR_CG-ConfigInfo.h"
|
||||
#include "NR_SecurityConfig.h"
|
||||
|
||||
int rrc_init_nr_global_param(void);
|
||||
|
||||
@@ -90,7 +91,10 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
int n_physical_antenna_ports,
|
||||
int initial_csi_index);
|
||||
|
||||
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig);
|
||||
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
|
||||
int eps_bearer_id, int rb_id,
|
||||
e_NR_CipheringAlgorithm ciphering_algorithm,
|
||||
e_NR_SecurityConfig__keyToUse key_to_use);
|
||||
|
||||
int generate_CG_Config(gNB_RRC_INST *rrc,
|
||||
NR_CG_Config_t *cg_Config,
|
||||
|
||||
@@ -103,7 +103,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
const uint8_t security_modeP,
|
||||
uint8_t *const kRRCenc,
|
||||
uint8_t *const kRRCint,
|
||||
uint8_t *const kUPenc
|
||||
uint8_t *const kUPenc,
|
||||
uint8_t *const kUPint
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
|
||||
#endif
|
||||
@@ -887,6 +888,7 @@ rrc_gNB_process_RRCReconfigurationComplete(
|
||||
kUPenc,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
/* Refresh SRBs/DRBs */
|
||||
nr_rrc_rlc_config_asn1_req(ctxt_pP,
|
||||
@@ -1702,6 +1704,7 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP,
|
||||
// NULL,
|
||||
// NULL,
|
||||
// NULL,
|
||||
// NULL,
|
||||
// NULL);
|
||||
|
||||
// if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) {
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "openair2/RRC/LTE/rrc_eNB_GTPV1U.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
|
||||
#include "UTIL/OSA/osa_defs.h"
|
||||
|
||||
extern boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
@@ -48,7 +49,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
const uint8_t security_modeP,
|
||||
uint8_t *const kRRCenc,
|
||||
uint8_t *const kRRCint,
|
||||
uint8_t *const kUPenc
|
||||
uint8_t *const kUPenc,
|
||||
uint8_t *const kUPint
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
|
||||
#endif
|
||||
@@ -115,28 +117,14 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, NR_UE_CapabilityRAT_ContainerL
|
||||
|
||||
// dump ue_capabilities
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1 && ueCapabilityRAT_Container_nr != NULL) ) {
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_nr != NULL ) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, ue_context_p->ue_context.UE_Capability_nr);
|
||||
}
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1 && ueCapabilityRAT_Container_MRDC != NULL) ) {
|
||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_MRDC != NULL ) {
|
||||
xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, ue_context_p->ue_context.UE_Capability_MRDC);
|
||||
}
|
||||
|
||||
if(cg_config_info && cg_config_info->mcg_RB_Config) {
|
||||
asn_dec_rval_t dec_rval = uper_decode(NULL,
|
||||
&asn_DEF_NR_RadioBearerConfig,
|
||||
(void **)&ue_context_p->ue_context.rb_config,
|
||||
cg_config_info->mcg_RB_Config->buf,
|
||||
cg_config_info->mcg_RB_Config->size, 0, 0);
|
||||
|
||||
if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
|
||||
AssertFatal(1==0,"[InterNode] Failed to decode mcg_rb_config (%zu bits), size of OCTET_STRING %lu\n",
|
||||
dec_rval.consumed, cg_config_info->mcg_RB_Config->size);
|
||||
}
|
||||
}
|
||||
|
||||
xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)ue_context_p->ue_context.rb_config);
|
||||
rrc_add_nsa_user(rrc,ue_context_p, m);
|
||||
}
|
||||
|
||||
@@ -152,6 +140,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
|
||||
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
|
||||
protocol_ctxt_t ctxt={0};
|
||||
unsigned char *kUPenc = NULL;
|
||||
int i;
|
||||
// NR RRCReconfiguration
|
||||
AssertFatal(rrc->Nb_ue < MAX_NR_RRC_UE_CONTEXTS,"cannot add another UE\n");
|
||||
ue_context_p->ue_context.reconfig = calloc(1,sizeof(NR_RRCReconfiguration_t));
|
||||
@@ -162,9 +152,91 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
NR_RRCReconfiguration_IEs_t *reconfig_ies=calloc(1,sizeof(NR_RRCReconfiguration_IEs_t));
|
||||
ue_context_p->ue_context.reconfig->criticalExtensions.choice.rrcReconfiguration = reconfig_ies;
|
||||
carrier->initial_csi_index[rrc->Nb_ue] = 0;
|
||||
ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t));
|
||||
if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1 || get_softmodem_params()->sa == 1){
|
||||
ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t));
|
||||
fill_default_rbconfig(ue_context_p->ue_context.rb_config);
|
||||
fill_default_rbconfig(ue_context_p->ue_context.rb_config,
|
||||
5 /* EPS bearer ID */,
|
||||
1 /* drb ID */,
|
||||
NR_CipheringAlgorithm_nea0,
|
||||
NR_SecurityConfig__keyToUse_master);
|
||||
} else {
|
||||
/* TODO: handle more than one bearer */
|
||||
if (m == NULL) {
|
||||
LOG_E(RRC, "fatal: m==NULL\n");
|
||||
exit(1);
|
||||
}
|
||||
if (m->nb_e_rabs_tobeadded != 1) {
|
||||
LOG_E(RRC, "fatal: m->nb_e_rabs_tobeadded = %d, should be 1\n", m->nb_e_rabs_tobeadded);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* store security key and security capabilities */
|
||||
memcpy(ue_context_p->ue_context.kgnb, m->kgnb, 32);
|
||||
ue_context_p->ue_context.security_capabilities.nRencryption_algorithms = m->security_capabilities.encryption_algorithms;
|
||||
ue_context_p->ue_context.security_capabilities.nRintegrity_algorithms = m->security_capabilities.integrity_algorithms;
|
||||
|
||||
/* Select ciphering algorithm based on gNB configuration file and
|
||||
* UE's supported algorithms.
|
||||
* We take the first from the list that is supported by the UE.
|
||||
* The ordering of the list comes from the configuration file.
|
||||
*/
|
||||
/* preset nea0 as fallback */
|
||||
ue_context_p->ue_context.ciphering_algorithm = 0;
|
||||
for (i = 0; i < rrc->security.ciphering_algorithms_count; i++) {
|
||||
int nea_mask[4] = {
|
||||
0,
|
||||
0x8000, /* nea1 */
|
||||
0x4000, /* nea2 */
|
||||
0x2000 /* nea3 */
|
||||
};
|
||||
if (rrc->security.ciphering_algorithms[i] == 0) {
|
||||
/* nea0 already preselected */
|
||||
break;
|
||||
}
|
||||
if (ue_context_p->ue_context.security_capabilities.nRencryption_algorithms & nea_mask[rrc->security.ciphering_algorithms[i]]) {
|
||||
ue_context_p->ue_context.ciphering_algorithm = rrc->security.ciphering_algorithms[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_I(RRC, "selecting ciphering algorithm %d\n", (int)ue_context_p->ue_context.ciphering_algorithm);
|
||||
|
||||
/* integrity: no integrity protection for DRB in ENDC mode
|
||||
* as written in 38.331: "If UE is connected to E-UTRA/EPC, this field
|
||||
* indicates the integrity protection algorithm to be used for SRBs
|
||||
* configured with NR PDCP, as specified in TS 33.501"
|
||||
* So nothing for DRB. Plus a test with a COTS UE revealed that it
|
||||
* did not apply integrity on the DRB.
|
||||
*/
|
||||
ue_context_p->ue_context.integrity_algorithm = 0;
|
||||
|
||||
LOG_I(RRC, "selecting integrity algorithm %d\n", ue_context_p->ue_context.integrity_algorithm);
|
||||
|
||||
/* derive UP security key */
|
||||
unsigned char *kUPenc_kdf;
|
||||
nr_derive_key_up_enc(ue_context_p->ue_context.ciphering_algorithm,
|
||||
ue_context_p->ue_context.kgnb,
|
||||
&kUPenc_kdf);
|
||||
/* kUPenc: last 128 bits of key derivation function which returns 256 bits */
|
||||
kUPenc = malloc(16);
|
||||
if (kUPenc == NULL) exit(1);
|
||||
memcpy(kUPenc, kUPenc_kdf+16, 16);
|
||||
free(kUPenc_kdf);
|
||||
|
||||
e_NR_CipheringAlgorithm cipher_algo;
|
||||
switch (ue_context_p->ue_context.ciphering_algorithm) {
|
||||
case 0: cipher_algo = NR_CipheringAlgorithm_nea0; break;
|
||||
case 1: cipher_algo = NR_CipheringAlgorithm_nea1; break;
|
||||
case 2: cipher_algo = NR_CipheringAlgorithm_nea2; break;
|
||||
case 3: cipher_algo = NR_CipheringAlgorithm_nea3; break;
|
||||
default: LOG_E(RRC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1);
|
||||
}
|
||||
|
||||
fill_default_rbconfig(ue_context_p->ue_context.rb_config,
|
||||
m->e_rabs_tobeadded[0].e_rab_id,
|
||||
m->e_rabs_tobeadded[0].drb_ID,
|
||||
cipher_algo,
|
||||
NR_SecurityConfig__keyToUse_secondary);
|
||||
}
|
||||
fill_default_reconfig(carrier->servingcellconfigcommon,
|
||||
reconfig_ies,
|
||||
@@ -285,10 +357,11 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
||||
(NR_SRB_ToAddModList_t *) NULL,
|
||||
ue_context_p->ue_context.rb_config->drb_ToAddModList ,
|
||||
ue_context_p->ue_context.rb_config->drb_ToReleaseList,
|
||||
0xff,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(ue_context_p->ue_context.integrity_algorithm << 4) | ue_context_p->ue_context.ciphering_algorithm,
|
||||
NULL, /* kRRCenc - unused */
|
||||
NULL, /* kRRCint - unused */
|
||||
kUPenc, /* kUPenc */
|
||||
NULL, /* kUPint - unused */
|
||||
NULL,
|
||||
NULL,
|
||||
ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList);
|
||||
|
||||
@@ -1334,7 +1334,10 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
||||
reconfig->nonCriticalExtension = NULL;
|
||||
}
|
||||
|
||||
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) {
|
||||
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
|
||||
int eps_bearer_id, int rb_id,
|
||||
e_NR_CipheringAlgorithm ciphering_algorithm,
|
||||
e_NR_SecurityConfig__keyToUse key_to_use) {
|
||||
|
||||
rbconfig->srb_ToAddModList = NULL;
|
||||
rbconfig->srb3_ToRelease = NULL;
|
||||
@@ -1342,8 +1345,8 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) {
|
||||
NR_DRB_ToAddMod_t *drb_ToAddMod = calloc(1,sizeof(*drb_ToAddMod));
|
||||
drb_ToAddMod->cnAssociation = calloc(1,sizeof(*drb_ToAddMod->cnAssociation));
|
||||
drb_ToAddMod->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity;
|
||||
drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= 5;
|
||||
drb_ToAddMod->drb_Identity = 1;
|
||||
drb_ToAddMod->cnAssociation->choice.eps_BearerIdentity= eps_bearer_id;
|
||||
drb_ToAddMod->drb_Identity = rb_id;
|
||||
drb_ToAddMod->reestablishPDCP = NULL;
|
||||
drb_ToAddMod->recoverPDCP = NULL;
|
||||
drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config));
|
||||
@@ -1372,12 +1375,12 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) {
|
||||
|
||||
rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig));
|
||||
rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig));
|
||||
rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0;
|
||||
rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = ciphering_algorithm;
|
||||
rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL;
|
||||
rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse));
|
||||
*rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master;
|
||||
*rbconfig->securityConfig->keyToUse = key_to_use;
|
||||
|
||||
xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig);
|
||||
// xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig);
|
||||
}
|
||||
/* Function to set or overwrite PTRS DL RRC parameters */
|
||||
void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset)
|
||||
|
||||
@@ -186,7 +186,8 @@ extern boolean_t nr_rrc_pdcp_config_asn1_req(
|
||||
const uint8_t security_modeP,
|
||||
uint8_t *const kRRCenc,
|
||||
uint8_t *const kRRCint,
|
||||
uint8_t *const kUPenc
|
||||
uint8_t *const kUPenc,
|
||||
uint8_t *const kUPint
|
||||
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
|
||||
,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9
|
||||
#endif
|
||||
@@ -1999,6 +2000,7 @@ nr_sa_rrc_ue_process_radioBearerConfig(
|
||||
// NULL,
|
||||
// NULL,
|
||||
// NULL,
|
||||
// NULL,
|
||||
// NULL);
|
||||
// Refresh SRBs
|
||||
// nr_rrc_rlc_config_asn1_req(ctxt_pP,
|
||||
@@ -2090,6 +2092,7 @@ nr_sa_rrc_ue_process_radioBearerConfig(
|
||||
// NULL,
|
||||
// kUPenc,
|
||||
// NULL,
|
||||
// NULL,
|
||||
// NR_UE_rrc_inst[ctxt_pP->module_id].defaultDRB,
|
||||
// NULL);
|
||||
// Refresh DRBs
|
||||
|
||||
@@ -53,6 +53,8 @@ typedef enum {
|
||||
|
||||
//int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB);
|
||||
|
||||
int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB);
|
||||
|
||||
int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
|
||||
const uint8_t key[32], uint8_t **out);
|
||||
int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
|
||||
|
||||
@@ -159,3 +159,27 @@ int derive_keNB(const uint8_t key[32], const uint32_t nas_count, uint8_t **keNB)
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB)
|
||||
{
|
||||
uint8_t *out;
|
||||
uint8_t s[5];
|
||||
|
||||
/* FC is 0x1c (see 3gpp 33.401 annex A.15) */
|
||||
s[0] = 0x1c;
|
||||
|
||||
/* put sk_counter */
|
||||
s[1] = (sk_counter >> 8) & 0xff;
|
||||
s[2] = sk_counter & 0xff;
|
||||
|
||||
/* put length of sk_counter (2) */
|
||||
s[3] = 0x00;
|
||||
s[4] = 0x02;
|
||||
|
||||
kdf(s, 5, keNB, 32, &out, 32);
|
||||
|
||||
memcpy(skgNB, out, 32);
|
||||
free(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user