diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index db82085ed6..c1eb645ed0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -298,7 +298,8 @@ void mac_top_init_gNB(ngran_node_t node_type, * will output the packets at a local interface, which is in line with * the noS1 mode. Hence, below, we simply hardcode ENB_FLAG_NO */ // setup PDCP, RLC - nr_pdcp_add_drbs(ENB_FLAG_NO, 0x1234, rbconfig->drb_ToAddModList, 0, NULL, NULL); + nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0}; + nr_pdcp_add_drbs(ENB_FLAG_NO, 0x1234, rbconfig->drb_ToAddModList, &null_security_parameters); nr_rlc_add_drb(0x1234, rbconfig->drb_ToAddModList->list.array[0]->drb_Identity, rlc_rbconfig); // free memory diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 2f7f4afa59..414edb052b 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -187,13 +187,15 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) // create PDCP bearers. This will also create SDAP bearers NR_DRB_ToAddModList_t DRB_configList = {0}; fill_DRB_configList_e1(&DRB_configList, req_pdu); + nr_pdcp_entity_security_keys_and_algos_t security_parameters; + security_parameters.ciphering_algorithm = req->cipheringAlgorithm; + security_parameters.integrity_algorithm = req->integrityProtectionAlgorithm; + memcpy(security_parameters.ciphering_key, req->encryptionKey, NR_K_KEY_SIZE); + memcpy(security_parameters.integrity_key, req->integrityProtectionKey, NR_K_KEY_SIZE); nr_pdcp_add_drbs(true, // set this to notify PDCP that his not UE cu_up_ue_id, &DRB_configList, - (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm, - (uint8_t *)req->encryptionKey, - (uint8_t *)req->integrityProtectionKey); - + &security_parameters); if (f1inst >= 0) { /* we have F1(-U) */ teid_t dummy_teid = 0xffff; // we will update later with answer from DU in_addr_t dummy_address = {0}; // IPv4, updated later with answer from DU @@ -255,7 +257,15 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) modified->id = to_modif->id; if (to_modif->pdcp_config.pDCP_Reestablishment) { - nr_pdcp_reestablishment(req->gNB_cu_up_ue_id, to_modif->id, false); + nr_pdcp_entity_security_keys_and_algos_t security_parameters; + security_parameters.ciphering_algorithm = req->cipheringAlgorithm; + security_parameters.integrity_algorithm = req->integrityProtectionAlgorithm; + memcpy(security_parameters.ciphering_key, req->encryptionKey, NR_K_KEY_SIZE); + memcpy(security_parameters.integrity_key, req->integrityProtectionKey, NR_K_KEY_SIZE); + nr_pdcp_reestablishment(req->gNB_cu_up_ue_id, + to_modif->id, + false, + &security_parameters); } if (f1inst < 0) // no F1-U? diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 712bbf6b0c..c125eb41f2 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -328,38 +328,35 @@ static bool nr_pdcp_entity_check_integrity(struct nr_pdcp_entity_t *entity, } /* may be called several times, take care to clean previous settings */ -static void nr_pdcp_entity_set_security(nr_pdcp_entity_t *entity, - int integrity_algorithm, - char *integrity_key, - int ciphering_algorithm, - char *ciphering_key) +static void nr_pdcp_entity_set_security(struct nr_pdcp_entity_t *entity, + const nr_pdcp_entity_security_keys_and_algos_t *parameters) { - if (integrity_algorithm != -1) - entity->integrity_algorithm = integrity_algorithm; - if (ciphering_algorithm != -1) - entity->ciphering_algorithm = ciphering_algorithm; - if (integrity_key != NULL) - memcpy(entity->integrity_key, integrity_key, 16); - if (ciphering_key != NULL) - memcpy(entity->ciphering_key, ciphering_key, 16); + if (parameters->integrity_algorithm != -1) { + entity->security_keys_and_algos.integrity_algorithm = parameters->integrity_algorithm; + memcpy(entity->security_keys_and_algos.integrity_key, parameters->integrity_key, NR_K_KEY_SIZE); + } + if (parameters->ciphering_algorithm != -1) { + entity->security_keys_and_algos.ciphering_algorithm = parameters->ciphering_algorithm; + memcpy(entity->security_keys_and_algos.ciphering_key, parameters->ciphering_key, NR_K_KEY_SIZE); + } - if (integrity_algorithm == 0) { + if (parameters->integrity_algorithm == 0) { entity->has_integrity = 0; if (entity->free_integrity != NULL) entity->free_integrity(entity->integrity_context); entity->free_integrity = NULL; } - if (integrity_algorithm != 0 && integrity_algorithm != -1) { + if (parameters->integrity_algorithm != 0 && parameters->integrity_algorithm != -1) { entity->has_integrity = 1; if (entity->free_integrity != NULL) entity->free_integrity(entity->integrity_context); - if (integrity_algorithm == 2) { - entity->integrity_context = nr_pdcp_integrity_nia2_init(entity->integrity_key); + if (parameters->integrity_algorithm == 2) { + entity->integrity_context = nr_pdcp_integrity_nia2_init(entity->security_keys_and_algos.integrity_key); entity->integrity = nr_pdcp_integrity_nia2_integrity; entity->free_integrity = nr_pdcp_integrity_nia2_free_integrity; - } else if (integrity_algorithm == 1) { - entity->integrity_context = nr_pdcp_integrity_nia1_init(entity->integrity_key); + } else if (parameters->integrity_algorithm == 1) { + entity->integrity_context = nr_pdcp_integrity_nia1_init(entity->security_keys_and_algos.integrity_key); entity->integrity = nr_pdcp_integrity_nia1_integrity; entity->free_integrity = nr_pdcp_integrity_nia1_free_integrity; } else { @@ -368,22 +365,22 @@ static void nr_pdcp_entity_set_security(nr_pdcp_entity_t *entity, } } - if (ciphering_algorithm == 0) { + if (parameters->ciphering_algorithm == 0) { entity->has_ciphering = 0; if (entity->free_security != NULL) entity->free_security(entity->security_context); entity->free_security = NULL; } - if (ciphering_algorithm != 0 && ciphering_algorithm != -1) { - if (ciphering_algorithm != 2) { + if (parameters->ciphering_algorithm != 0 && parameters->ciphering_algorithm != -1) { + if (parameters->ciphering_algorithm != 2) { LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n"); exit(1); } entity->has_ciphering = 1; if (entity->free_security != NULL) entity->free_security(entity->security_context); - entity->security_context = nr_pdcp_security_nea2_init(entity->ciphering_key); + entity->security_context = nr_pdcp_security_nea2_init(entity->security_keys_and_algos.ciphering_key); entity->cipher = nr_pdcp_security_nea2_cipher; entity->free_security = nr_pdcp_security_nea2_free_security; } @@ -515,23 +512,27 @@ static void free_rx_list(nr_pdcp_entity_t *entity) * @brief PDCP entity re-establishment according to 5.1.2 of 3GPP TS 38.323 * @todo deal with ciphering/integrity algos and keys for transmitting/receiving entity procedures */ -static void nr_pdcp_entity_reestablish_drb_am(nr_pdcp_entity_t *entity) +static void nr_pdcp_entity_reestablish_drb_am(nr_pdcp_entity_t *entity, + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { /* transmitting entity procedures */ - /* todo: deal with ciphering/integrity algos and keys */ + /* do nothing */ /* receiving entity procedures */ - /* todo: deal with ciphering/integrity algos and keys */ + /* do nothing */ + + /* ciphering and integrity: common for both tx and rx entities */ + entity->set_security(entity, security_parameters); /* Flag PDCP entity as re-established */ entity->entity_suspended = false; } -static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity) +static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity, + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { /* transmitting entity procedures */ entity->tx_next = 0; - /* todo: deal with ciphering/integrity algos and keys */ /* receiving entity procedures */ /* deliver all SDUs if t_reordering is running */ @@ -542,17 +543,19 @@ static void nr_pdcp_entity_reestablish_drb_um(nr_pdcp_entity_t *entity) /* set rx_next and rx_deliv to the initial value */ entity->rx_next = 0; entity->rx_deliv = 0; - /* todo: deal with ciphering/integrity algos and keys */ + + /* ciphering and integrity: common for both tx and rx entities */ + entity->set_security(entity, security_parameters); /* Flag PDCP entity as re-established */ entity->entity_suspended = false; } -static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity) +static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity, + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { /* transmitting entity procedures */ entity->tx_next = 0; - /* todo: deal with ciphering/integrity algos and keys */ /* receiving entity procedures */ free_rx_list(entity); @@ -561,7 +564,9 @@ static void nr_pdcp_entity_reestablish_srb(nr_pdcp_entity_t *entity) /* set rx_next and rx_deliv to the initial value */ entity->rx_next = 0; entity->rx_deliv = 0; - /* todo: deal with ciphering/integrity algos and keys */ + + /* ciphering and integrity: common for both tx and rx entities */ + entity->set_security(entity, security_parameters); /* Flag PDCP entity as re-established */ entity->entity_suspended = false; @@ -606,10 +611,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( int sn_size, int t_reordering, int discard_timer, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key) + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { nr_pdcp_entity_t *ret; @@ -663,9 +665,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( ret->is_gnb = is_gnb; - nr_pdcp_entity_set_security(ret, - integrity_algorithm, (char *)integrity_key, - ciphering_algorithm, (char *)ciphering_key); + nr_pdcp_entity_set_security(ret, security_parameters); return ret; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index d26ce83b82..a5ef870749 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -48,6 +48,13 @@ typedef enum { NR_PDCP_SRB } nr_pdcp_entity_type_t; +typedef struct { + int integrity_algorithm; + int ciphering_algorithm; + uint8_t integrity_key[NR_K_KEY_SIZE]; + uint8_t ciphering_key[NR_K_KEY_SIZE]; +} nr_pdcp_entity_security_keys_and_algos_t; + typedef struct { //nr_pdcp_entity_type_t mode; /* PDU stats */ @@ -91,19 +98,15 @@ typedef struct nr_pdcp_entity_t { void (*delete_entity)(struct nr_pdcp_entity_t *entity); void (*release_entity)(struct nr_pdcp_entity_t *entity); void (*suspend_entity)(struct nr_pdcp_entity_t *entity); - void (*reestablish_entity)(struct nr_pdcp_entity_t *entity); + void (*reestablish_entity)(struct nr_pdcp_entity_t *entity, + const nr_pdcp_entity_security_keys_and_algos_t *parameters); void (*get_stats)(struct nr_pdcp_entity_t *entity, nr_pdcp_statistics_t *out); - /* set_security: pass -1 to integrity_algorithm / ciphering_algorithm - * to keep the current algorithm - * pass NULL to integrity_key / ciphering_key - * to keep the current key + /* set_security: pass -1 to parameters->integrity_algorithm / parameters->ciphering_algorithm + * to keep the corresponding current algorithm and key */ void (*set_security)(struct nr_pdcp_entity_t *entity, - int integrity_algorithm, - char *integrity_key, - int ciphering_algorithm, - char *ciphering_key); + const nr_pdcp_entity_security_keys_and_algos_t *parameters); /* check_integrity is used by RRC */ bool (*check_integrity)(struct nr_pdcp_entity_t *entity, @@ -148,10 +151,7 @@ typedef struct nr_pdcp_entity_t { /* security */ int has_ciphering; int has_integrity; - int ciphering_algorithm; - int integrity_algorithm; - unsigned char ciphering_key[16]; - unsigned char integrity_key[16]; + nr_pdcp_entity_security_keys_and_algos_t security_keys_and_algos; stream_security_context_t *security_context; void (*cipher)(stream_security_context_t *security_context, unsigned char *buffer, int length, @@ -196,10 +196,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( int sn_size, int t_reordering, int discard_timer, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key); + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); /* Get maximum PDCP PDU size */ int nr_max_pdcp_pdu_size(sdu_size_t sdu_size); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 17b1b02408..4582a85795 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -798,10 +798,7 @@ void deliver_pdu_srb_rlc(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, void add_srb(int is_gnb, ue_id_t UEid, struct NR_SRB_ToAddMod *s, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key) + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { nr_pdcp_entity_t *pdcp_srb; nr_pdcp_ue_t *ue; @@ -829,10 +826,7 @@ void add_srb(int is_gnb, SHORT_SN_SIZE, t_Reordering, -1, - ciphering_algorithm, - integrity_algorithm, - ciphering_key, - integrity_key); + security_parameters); nr_pdcp_ue_add_srb_pdcp_entity(ue, srb_id, pdcp_srb); LOG_D(PDCP, "added srb %d to UE ID %ld\n", srb_id, UEid); @@ -843,10 +837,7 @@ void add_srb(int is_gnb, void add_drb(int is_gnb, ue_id_t UEid, struct NR_DRB_ToAddMod *s, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key) + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { nr_pdcp_entity_t *pdcp_drb; nr_pdcp_ue_t *ue; @@ -910,6 +901,10 @@ void add_drb(int is_gnb, exit(1); } + /* get actual ciphering and integrity algorithm based on pdcp_Config */ + nr_pdcp_entity_security_keys_and_algos_t actual_security_parameters = *security_parameters; + actual_security_parameters.ciphering_algorithm = has_ciphering ? security_parameters->ciphering_algorithm : 0; + actual_security_parameters.integrity_algorithm = has_integrity ? security_parameters->integrity_algorithm : 0; nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, UEid); @@ -922,10 +917,7 @@ void add_drb(int is_gnb, deliver_pdu_drb_gnb : deliver_pdu_drb_ue, ue, sn_size_dl, t_reordering, discard_timer, - has_ciphering ? ciphering_algorithm : 0, - has_integrity ? integrity_algorithm : 0, - has_ciphering ? ciphering_key : NULL, - has_integrity ? integrity_key : NULL); + &actual_security_parameters); nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); LOG_I(PDCP, "added drb %d to UE ID %ld\n", drb_id, UEid); @@ -946,13 +938,11 @@ void add_drb(int is_gnb, void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t UEid, NR_SRB_ToAddModList_t *const srb2add_list, - const uint8_t security_modeP, - uint8_t *const kRRCenc, - uint8_t *const kRRCint) + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { if (srb2add_list != NULL) { for (int i = 0; i < srb2add_list->list.count; i++) { - add_srb(enb_flag, UEid, srb2add_list->list.array[i], security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, kRRCenc, kRRCint); + add_srb(enb_flag, UEid, srb2add_list->list.array[i], security_parameters); } } else LOG_W(PDCP, "nr_pdcp_add_srbs() with void list\n"); @@ -961,19 +951,14 @@ void nr_pdcp_add_srbs(eNB_flag_t enb_flag, void nr_pdcp_add_drbs(eNB_flag_t enb_flag, ue_id_t UEid, NR_DRB_ToAddModList_t *const drb2add_list, - const uint8_t security_modeP, - uint8_t *const kUPenc, - uint8_t *const kUPint) + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { if (drb2add_list != NULL) { for (int i = 0; i < drb2add_list->list.count; i++) { add_drb(enb_flag, UEid, drb2add_list->list.array[i], - security_modeP & 0x0f, - (security_modeP >> 4) & 0x0f, - kUPenc, - kUPint); + security_parameters); } } else LOG_W(PDCP, "nr_pdcp_add_drbs() with void list\n"); @@ -1026,35 +1011,26 @@ void pdcp_config_set_security(const protocol_ctxt_t *const ctxt_pP, } void nr_pdcp_config_set_security(ue_id_t ue_id, - const rb_id_t rb_id, - const uint8_t security_modeP, - uint8_t *const kRRCenc_pP, - uint8_t *const kRRCint_pP, - uint8_t *const kUPenc_pP) + rb_id_t rb_id, + bool is_srb, + const nr_pdcp_entity_security_keys_and_algos_t *parameters) { nr_pdcp_ue_t *ue; nr_pdcp_entity_t *rb; - int integrity_algorithm; - int ciphering_algorithm; nr_pdcp_manager_lock(nr_pdcp_ue_manager); ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - /* TODO: proper handling of DRBs, for the moment only SRBs are handled */ - - rb = nr_pdcp_get_rb(ue, rb_id, true); + rb = nr_pdcp_get_rb(ue, rb_id, is_srb); if (rb == NULL) { nr_pdcp_manager_unlock(nr_pdcp_ue_manager); - LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %ld)\n", ue_id, rb_id); + LOG_E(PDCP, "no %s found (ue_id %ld, rb_id %ld)\n", is_srb ? "SRB" : "DRB", ue_id, rb_id); return; } - integrity_algorithm = (security_modeP>>4) & 0xf; - ciphering_algorithm = security_modeP & 0x0f; - rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP, - ciphering_algorithm, (char *)kRRCenc_pP); + rb->set_security(rb, parameters); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } @@ -1240,7 +1216,10 @@ void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag) +void nr_pdcp_reestablishment(ue_id_t ue_id, + int rb_id, + bool srb_flag, + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters) { nr_pdcp_ue_t *ue; nr_pdcp_entity_t *rb; @@ -1251,7 +1230,7 @@ void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag) if (rb != NULL) { LOG_D(PDCP, "UE %4.4lx re-establishment of %sRB %d\n", ue_id, srb_flag ? "S" : "D", rb_id); - rb->reestablish_entity(rb); + rb->reestablish_entity(rb, security_parameters); LOG_I(PDCP, "%s %d re-established\n", srb_flag ? "SRB" : "DRB" , rb_id); } else { LOG_W(PDCP, "UE %4.4lx cannot re-establish %sRB %d, RB not found\n", ue_id, srb_flag ? "S" : "D", rb_id); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index 99f7fcdc81..54a5e0dcbc 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -49,20 +49,23 @@ bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, void nr_pdcp_add_drbs(eNB_flag_t enb_flag, ue_id_t UEid, NR_DRB_ToAddModList_t *const drb2add_list, - const uint8_t security_modeP, - uint8_t *const kUPenc, - uint8_t *const kUPint); + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); + +void nr_pdcp_add_srbs(eNB_flag_t enb_flag, + ue_id_t UEid, + NR_SRB_ToAddModList_t *const srb2add_list, + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); void add_drb(int is_gnb, ue_id_t UEid, struct NR_DRB_ToAddMod *s, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key); + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); void nr_pdcp_remove_UE(ue_id_t ue_id); -void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag); +void nr_pdcp_reestablishment(ue_id_t ue_id, + int rb_id, + bool srb_flag, + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); void nr_pdcp_suspend_srb(ue_id_t ue_id, int srb_id); void nr_pdcp_suspend_drb(ue_id_t ue_id, int drb_id); @@ -71,21 +74,15 @@ void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, NR_PDCP_Config_t *pdcp_c void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id); void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id); - void add_srb(int is_gnb, ue_id_t UEid, struct NR_SRB_ToAddMod *s, - int ciphering_algorithm, - int integrity_algorithm, - unsigned char *ciphering_key, - unsigned char *integrity_key); + const nr_pdcp_entity_security_keys_and_algos_t *security_parameters); void nr_pdcp_config_set_security(ue_id_t ue_id, - const rb_id_t rb_id, - const uint8_t security_modeP, - uint8_t *const kRRCenc_pP, - uint8_t *const kRRCint_pP, - uint8_t *const kUPenc_pP); + rb_id_t rb_id, + bool is_srb, + const nr_pdcp_entity_security_keys_and_algos_t *parameters); bool nr_pdcp_check_integrity_srb(ue_id_t ue_id, int srb_id, diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 9ae787bd7e..d5aee94aab 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -145,20 +145,6 @@ void ue_cxt_mod_direct(MessageDef *msg, void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp); -void nr_pdcp_add_srbs(eNB_flag_t enb_flag, - ue_id_t UEid, - NR_SRB_ToAddModList_t *const srb2add_list, - const uint8_t security_modeP, - uint8_t *const kRRCenc, - uint8_t *const kUPint); - -void nr_pdcp_add_drbs(eNB_flag_t enb_flag, - ue_id_t rntiMaybeUEid, - NR_DRB_ToAddModList_t *const drb2add_list, - const uint8_t security_modeP, - uint8_t *const kUPenc, - uint8_t *const kUPint); - void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink); int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint32_t tmsi, uint8_t paging_drx); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index d22e25187d..266728fd54 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -389,19 +389,19 @@ static void activate_srb(gNB_RRC_UE_t *UE, int srb_id) srb->srb_Identity = srb_id; if (srb_id == 1) { - nr_pdcp_add_srbs(true, UE->rrc_ue_id, list, 0, NULL, NULL); + nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0}; + nr_pdcp_add_srbs(true, UE->rrc_ue_id, list, &null_security_parameters); } else { - uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; - uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; - nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc); - nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint); + nr_pdcp_entity_security_keys_and_algos_t security_parameters; + security_parameters.ciphering_algorithm = UE->ciphering_algorithm; + security_parameters.integrity_algorithm = UE->integrity_algorithm; + nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, security_parameters.ciphering_key); + nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, security_parameters.integrity_key); nr_pdcp_add_srbs(true, UE->rrc_ue_id, list, - (UE->integrity_algorithm << 4) | UE->ciphering_algorithm, - kRRCenc, - kRRCint); + &security_parameters); } freeSRBlist(list); } @@ -850,6 +850,12 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) /* increase DRB to modify counter */ pdu_e1->numDRB2Modify += 1; } + + req.cipheringAlgorithm = rrc->security.do_drb_ciphering ? ue_p->ciphering_algorithm : 0; + req.integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? ue_p->integrity_algorithm : 0; + nr_derive_key(UP_ENC_ALG, req.cipheringAlgorithm, ue_p->kgnb, (uint8_t *)req.encryptionKey); + nr_derive_key(UP_INT_ALG, req.integrityProtectionAlgorithm, ue_p->kgnb, (uint8_t *)req.integrityProtectionKey); + /* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p); rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); @@ -866,7 +872,6 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context { module_id_t module_id = 0; gNB_RRC_INST *rrc = RC.nrrrc[module_id]; - int enable_ciphering = 0; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; uint8_t buffer[RRC_BUF_SIZE] = {0}; uint8_t xid = rrc_gNB_get_next_transaction_identifier(module_id); @@ -878,30 +883,33 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size); /* Ciphering and Integrity according to TS 33.501 */ - uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; - uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; - uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; + nr_pdcp_entity_security_keys_and_algos_t security_parameters; /* Derive the keys from kgnb */ - if (ue_p->Srb[1].Active) - nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc); - nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc); - nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint); + nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, security_parameters.ciphering_key); + nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, security_parameters.integrity_key); LOG_I(NR_RRC, - "Set PDCP security UE %d RNTI %04x nca %ld nia %d in RRCReestablishment\n", + "Set PDCP security UE %d RNTI %04x nea %ld nia %d in RRCReestablishment\n", ue_p->rrc_ue_id, ue_p->rnti, ue_p->ciphering_algorithm, ue_p->integrity_algorithm); - uint8_t security_mode = - enable_ciphering ? ue_p->ciphering_algorithm | (ue_p->integrity_algorithm << 4) : 0 | (ue_p->integrity_algorithm << 4); + /* RRCReestablishment is integrity protected but not ciphered, + * so let's configure only integrity protection right now. + * Ciphering is enabled below, after generating RRCReestablishment. + */ + security_parameters.integrity_algorithm = ue_p->integrity_algorithm; + security_parameters.ciphering_algorithm = 0; /* SRBs */ for (int srb_id = 1; srb_id < NR_NUM_SRB; srb_id++) { if (ue_p->Srb[srb_id].Active) - nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); + nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, true, &security_parameters); } /* Re-establish PDCP for SRB1, according to 5.3.7.4 of 3GPP TS 38.331 */ - nr_pdcp_reestablishment(ue_p->rrc_ue_id, 1, true); + nr_pdcp_reestablishment(ue_p->rrc_ue_id, + 1, + true, + &security_parameters); /* F1AP DL RRC Message Transfer */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data); @@ -912,6 +920,14 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context .old_gNB_DU_ue_id = &old_gNB_DU_ue_id}; deliver_dl_rrc_message_data_t data = {.rrc = rrc, .dl_rrc = &dl_rrc, .assoc_id = ue_data.du_assoc_id}; nr_pdcp_data_req_srb(ue_p->rrc_ue_id, DCCH, rrc_gNB_mui++, size, (unsigned char *const)buffer, rrc_deliver_dl_rrc_message, &data); + + /* RRCReestablishment has been generated, let's enable ciphering now. */ + security_parameters.ciphering_algorithm = ue_p->ciphering_algorithm; + /* SRBs */ + for (int srb_id = 1; srb_id < NR_NUM_SRB; srb_id++) { + if (ue_p->Srb[srb_id].Active) + nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, true, &security_parameters); + } } /// @brief Function tha processes RRCReestablishmentComplete message sent by the UE, after RRCReestasblishment request. @@ -933,9 +949,6 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co ue_p->Srb[1].Active = 1; - uint8_t send_security_mode_command = false; - nr_rrc_pdcp_config_security(ctxt_pP, ue_context_pP, send_security_mode_command); - gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t)); @@ -966,7 +979,13 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co */ int srb_id = 2; if (ue_p->Srb[srb_id].Active) { - nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true); + nr_pdcp_entity_security_keys_and_algos_t security_parameters; + security_parameters.ciphering_algorithm = ue_p->ciphering_algorithm; + security_parameters.integrity_algorithm = ue_p->integrity_algorithm; + nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, security_parameters.ciphering_key); + nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, security_parameters.integrity_key); + + nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true, &security_parameters); } /* PDCP Reestablishment of DRBs according to 5.3.5.6.5 of 3GPP TS 38.331 (over E1) */ cuup_notify_reestablishment(rrc, ue_p); @@ -1891,6 +1910,11 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f DevAssert(req.numPDUSessionsMod > 0); DevAssert(req.numPDUSessions == 0); + req.cipheringAlgorithm = rrc->security.do_drb_ciphering ? UE->ciphering_algorithm : 0; + req.integrityProtectionAlgorithm = rrc->security.do_drb_integrity ? UE->integrity_algorithm : 0; + nr_derive_key(UP_ENC_ALG, req.cipheringAlgorithm, UE->kgnb, (uint8_t *)req.encryptionKey); + nr_derive_key(UP_INT_ALG, req.integrityProtectionAlgorithm, UE->kgnb, (uint8_t *)req.integrityProtectionKey); + // send the E1 bearer modification request message to update F1-U tunnel info sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE); rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index d024eff20f..a8568fe724 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -135,33 +135,29 @@ nr_rrc_pdcp_config_security( ) //------------------------------------------------------------------------------ { - uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; - uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; - uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; //uint8_t *k_kdf = NULL; static int print_keys= 1; gNB_RRC_UE_t *UE = &ue_context_pP->ue_context; /* Derive the keys from kgnb */ - if (UE->Srb[1].Active || UE->Srb[2].Active) { - nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc); - } - - nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc); - nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint); + nr_pdcp_entity_security_keys_and_algos_t security_parameters; + /* set ciphering algorithm depending on 'enable_ciphering' */ + security_parameters.ciphering_algorithm = enable_ciphering ? UE->ciphering_algorithm : 0; + security_parameters.integrity_algorithm = UE->integrity_algorithm; + /* use current ciphering algorithm, independently of 'enable_ciphering' to derive ciphering key */ + nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, security_parameters.ciphering_key); + nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, security_parameters.integrity_key); if ( LOG_DUMPFLAG( DEBUG_SECURITY ) ) { if (print_keys == 1 ) { print_keys =0; LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, UE->kgnb, 32, "\nKgNB:"); - LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, kRRCenc, 16,"\nKRRCenc:" ); - LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, kRRCint, 16,"\nKRRCint:" ); + LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, security_parameters.ciphering_key, 16,"\nKRRCenc:" ); + LOG_DUMPMSG(NR_RRC, DEBUG_SECURITY, security_parameters.integrity_key, 16,"\nKRRCint:" ); } } - uint8_t security_mode = - enable_ciphering ? UE->ciphering_algorithm | (UE->integrity_algorithm << 4) : 0 | (UE->integrity_algorithm << 4); - nr_pdcp_config_set_security(ctxt_pP->rntiMaybeUEid, DCCH, security_mode, kRRCenc, kRRCint, kUPenc); + nr_pdcp_config_set_security(ctxt_pP->rntiMaybeUEid, DCCH, true, &security_parameters); } //------------------------------------------------------------------------------ diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 0aad9ea503..4347b83a19 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -126,8 +126,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a gtpv1u_enb_create_tunnel_req_t create_tunnel_req; gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; protocol_ctxt_t ctxt={0}; - uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; - uint8_t kUPint[NR_K_KEY_SIZE] = {0}; + nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0}; int i; gNB_RRC_UE_t *UE = &ue_context_p->ue_context; @@ -218,8 +217,10 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a LOG_I(RRC, "selecting integrity algorithm %d\n", UE->integrity_algorithm); /* derive UP security key */ - nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc); - nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, kUPint); + security_parameters.ciphering_algorithm = UE->ciphering_algorithm; + security_parameters.integrity_algorithm = UE->integrity_algorithm; + nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, security_parameters.ciphering_key); + nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, security_parameters.integrity_key); e_NR_CipheringAlgorithm cipher_algo; switch (UE->ciphering_algorithm) { @@ -388,9 +389,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a nr_pdcp_add_drbs(ctxt.enb_flag, rrc_ue_id, ue_context_p->ue_context.rb_config->drb_ToAddModList, - (ue_context_p->ue_context.integrity_algorithm << 4) | ue_context_p->ue_context.ciphering_algorithm, - kUPenc, - kUPint); + &security_parameters); ctxt.rntiMaybeUEid = du_ue_id; // assume only a single bearer diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 980f793c0a..3098cb974c 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -631,14 +631,14 @@ static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti) nr_timer_start(&tac->T301); int srb_id = 1; // re-establish PDCP for SRB1 - nr_pdcp_reestablishment(rrc->ue_id, srb_id, true); + // (and suspend integrity protection and ciphering for SRB1) + nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0}; + nr_pdcp_reestablishment(rrc->ue_id, srb_id, true, &null_security_parameters); // re-establish RLC for SRB1 int lc_id = nr_rlc_get_lcid_from_rb(rrc->ue_id, true, 1); nr_rlc_reestablish_entity(rrc->ue_id, lc_id); // apply the specified configuration defined in 9.2.1 for SRB1 nr_rlc_reconfigure_entity(rrc->ue_id, lc_id, NULL); - // suspend integrity protection and ciphering for SRB1 - nr_pdcp_config_set_security(rrc->ue_id, srb_id, 0, NULL, NULL, NULL); // resume SRB1 rrc->Srb[srb_id] = RB_ESTABLISHED; break; @@ -1047,21 +1047,19 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, ue_rrc->integrityProtAlgorithm = *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm; } - uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; - uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; - uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; - nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kUPenc); - nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc); - nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint); + nr_pdcp_entity_security_keys_and_algos_t security_parameters; + nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, security_parameters.ciphering_key); + nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, security_parameters.integrity_key); - log_dump(NR_RRC, ue_rrc->kgnb, 32, LOG_DUMP_CHAR, "deriving kRRCenc, kRRCint and kUPenc from KgNB="); + log_dump(NR_RRC, ue_rrc->kgnb, 32, LOG_DUMP_CHAR, "deriving kRRCenc, kRRCint from KgNB="); /* for SecurityModeComplete, ciphering is not activated yet, only integrity */ - uint8_t security_mode = ue_rrc->integrityProtAlgorithm << 4; + security_parameters.ciphering_algorithm = 0; + security_parameters.integrity_algorithm = ue_rrc->integrityProtAlgorithm; // configure lower layers to apply SRB integrity protection and ciphering for (int i = 1; i < NR_NUM_SRB; i++) { if (ue_rrc->Srb[i] == RB_ESTABLISHED) - nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, kRRCenc, kRRCint, kUPenc); + nr_pdcp_config_set_security(ue_rrc->ue_id, i, true, &security_parameters); } NR_UL_DCCH_Message_t ul_dcch_msg = {0}; @@ -1094,10 +1092,10 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg); /* disable both ciphering and integrity */ - security_mode = 0; + nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0}; for (int i = 1; i < NR_NUM_SRB; i++) { if (ue_rrc->Srb[i] == RB_ESTABLISHED) - nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, NULL, NULL, NULL); + nr_pdcp_config_set_security(ue_rrc->ue_id, i, true, &null_security_parameters); } srb_id = 1; // SecurityModeFailure in SRB1 @@ -1139,12 +1137,11 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); /* after encoding SecurityModeComplete we activate both ciphering and integrity */ - security_mode = ue_rrc->cipheringAlgorithm | (ue_rrc->integrityProtAlgorithm << 4); + security_parameters.ciphering_algorithm = ue_rrc->cipheringAlgorithm; // configure lower layers to apply SRB integrity protection and ciphering for (int i = 1; i < NR_NUM_SRB; i++) { if (ue_rrc->Srb[i] == RB_ESTABLISHED) - /* pass NULL to keep current keys */ - nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, NULL, NULL, NULL); + nr_pdcp_config_set_security(ue_rrc->ue_id, i, true, &security_parameters); } } @@ -1416,10 +1413,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, ue_rrc->Srb[3] = RB_NOT_PRESENT; } - uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; - uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; - uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; - uint8_t kUPint[NR_K_KEY_SIZE] = {0}; + nr_pdcp_entity_security_keys_and_algos_t security_rrc_parameters = {0}; + nr_pdcp_entity_security_keys_and_algos_t security_up_parameters = {0}; if (ue_rrc->as_security_activated) { if (radioBearerConfig->securityConfig != NULL) { @@ -1435,10 +1430,14 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, ue_rrc->integrityProtAlgorithm = *radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm; } } - nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc); - nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint); - nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kUPenc); - nr_derive_key(UP_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kUPint); + security_rrc_parameters.ciphering_algorithm = ue_rrc->cipheringAlgorithm; + security_rrc_parameters.integrity_algorithm = ue_rrc->integrityProtAlgorithm; + nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, security_rrc_parameters.ciphering_key); + nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, security_rrc_parameters.integrity_key); + security_up_parameters.ciphering_algorithm = ue_rrc->cipheringAlgorithm; + security_up_parameters.integrity_algorithm = ue_rrc->integrityProtAlgorithm; + nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, security_up_parameters.ciphering_key); + nr_derive_key(UP_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, security_up_parameters.integrity_key); } if (radioBearerConfig->srb_ToAddModList != NULL) { @@ -1449,18 +1448,16 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, add_srb(false, ue_rrc->ue_id, radioBearerConfig->srb_ToAddModList->list.array[cnt], - ue_rrc->cipheringAlgorithm, - ue_rrc->integrityProtAlgorithm, - kRRCenc, - kRRCint); + &security_rrc_parameters); } else { AssertFatal(srb->discardOnPDCP == NULL, "discardOnPDCP not yet implemented\n"); if (srb->reestablishPDCP) { ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED; - nr_pdcp_reestablishment(ue_rrc->ue_id, srb->srb_Identity, true); - // TODO configure the PDCP entity to apply the integrity protection algorithm - // TODO configure the PDCP entity to apply the ciphering algorithm + nr_pdcp_reestablishment(ue_rrc->ue_id, + srb->srb_Identity, + true, + &security_rrc_parameters); } if (srb->pdcp_Config && srb->pdcp_Config->t_Reordering) nr_pdcp_reconfigure_srb(ue_rrc->ue_id, srb->srb_Identity, *srb->pdcp_Config->t_Reordering); @@ -1489,9 +1486,20 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, if (get_DRB_status(ue_rrc, DRB_id) != RB_NOT_PRESENT) { if (drb->reestablishPDCP) { set_DRB_status(ue_rrc, DRB_id, RB_ESTABLISHED); - nr_pdcp_reestablishment(ue_rrc->ue_id, DRB_id, false); - // TODO configure the PDCP entity to apply the integrity protection algorithm - // TODO configure the PDCP entity to apply the ciphering algorithm + /* get integrity and cipehring settings from radioBearerConfig */ + bool has_integrity = drb->pdcp_Config != NULL + && drb->pdcp_Config->drb != NULL + && drb->pdcp_Config->drb->integrityProtection != NULL; + bool has_ciphering = !(drb->pdcp_Config != NULL + && drb->pdcp_Config->ext1 != NULL + && drb->pdcp_Config->ext1->cipheringDisabled != NULL); + security_up_parameters.ciphering_algorithm = has_ciphering ? ue_rrc->cipheringAlgorithm : 0; + security_up_parameters.integrity_algorithm = has_integrity ? ue_rrc->integrityProtAlgorithm : 0; + /* re-establish */ + nr_pdcp_reestablishment(ue_rrc->ue_id, + DRB_id, + false, + &security_up_parameters); } AssertFatal(drb->recoverPDCP == NULL, "recoverPDCP not yet implemented\n"); /* sdap-Config is included (SA mode) */ @@ -1507,10 +1515,7 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, add_drb(false, ue_rrc->ue_id, radioBearerConfig->drb_ToAddModList->list.array[cnt], - ue_rrc->cipheringAlgorithm, - ue_rrc->integrityProtAlgorithm, - kUPenc, - kUPint); + &security_up_parameters); } } } // drb_ToAddModList // @@ -1550,17 +1555,13 @@ static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc, // update the K gNB key based on the current K gNB key or the NH, using the stored nextHopChainingCount value nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb); - // derive the K RRCenc and K UPenc keys associated with the previously configured cipheringAlgorithm - // derive the K RRCint and K UPint keys associated with the previously configured integrityProtAlgorithm - uint8_t kRRCenc[16] = {0}; - uint8_t kRRCint[16] = {0}; - uint8_t kUPenc[16] = {0}; - uint8_t kUPint[16] = {0}; - - nr_derive_key(UP_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, kUPenc); - nr_derive_key(UP_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, kUPint); - nr_derive_key(RRC_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, kRRCenc); - nr_derive_key(RRC_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, kRRCint); + // derive the K RRCenc key associated with the previously configured cipheringAlgorithm + // derive the K RRCint key associated with the previously configured integrityProtAlgorithm + nr_pdcp_entity_security_keys_and_algos_t security_parameters; + security_parameters.ciphering_algorithm = rrc->cipheringAlgorithm; + security_parameters.integrity_algorithm = rrc->integrityProtAlgorithm; + nr_derive_key(RRC_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, security_parameters.ciphering_key); + nr_derive_key(RRC_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, security_parameters.integrity_key); // TODO request lower layers to verify the integrity protection of the RRCReestablishment message // TODO if the integrity protection check of the RRCReestablishment message fails -> go to IDLE @@ -1568,9 +1569,7 @@ static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc, // configure lower layers to resume integrity protection for SRB1 // configure lower layers to resume ciphering for SRB1 int srb_id = 1; - int security_mode = (rrc->integrityProtAlgorithm << 4) - | rrc->cipheringAlgorithm; - nr_pdcp_config_set_security(rrc->ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); + nr_pdcp_config_set_security(rrc->ue_id, srb_id, true, &security_parameters); // release the measurement gap configuration indicated by the measGapConfig, if configured rrcPerNB_t *rrcNB = rrc->perNB + gNB_index;