diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 2f7f4afa59..66118c9ac7 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -255,7 +255,13 @@ 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_reestablishment(req->gNB_cu_up_ue_id, + to_modif->id, + false, + req->integrityProtectionAlgorithm, + (uint8_t *)req->integrityProtectionKey, + req->cipheringAlgorithm, + (uint8_t *)req->encryptionKey); } 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 d1eccdee5a..1d17516fe0 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -515,23 +515,33 @@ 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, + int integrity_algorithm, + const uint8_t *integrity_key, + int ciphering_algorithm, + const uint8_t *ciphering_key) { /* 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, integrity_algorithm, integrity_key, ciphering_algorithm, ciphering_key); /* 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, + int integrity_algorithm, + const uint8_t *integrity_key, + int ciphering_algorithm, + const uint8_t *ciphering_key) { /* 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 +552,22 @@ 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, integrity_algorithm, integrity_key, ciphering_algorithm, ciphering_key); /* 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, + int integrity_algorithm, + const uint8_t *integrity_key, + int ciphering_algorithm, + const uint8_t *ciphering_key) { /* transmitting entity procedures */ entity->tx_next = 0; - /* todo: deal with ciphering/integrity algos and keys */ /* receiving entity procedures */ free_rx_list(entity); @@ -561,7 +576,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, integrity_algorithm, integrity_key, ciphering_algorithm, ciphering_key); /* Flag PDCP entity as re-established */ entity->entity_suspended = false; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 50ad0d1312..2fe6c36695 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -91,7 +91,11 @@ 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, + int integrity_algorithm, + const uint8_t *integrity_key, + int ciphering_algorithm, + const uint8_t *ciphering_key); void (*get_stats)(struct nr_pdcp_entity_t *entity, nr_pdcp_statistics_t *out); /* set_security: pass -1 to integrity_algorithm / ciphering_algorithm diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index 65e2dbbcbf..bae1cf86f7 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -62,7 +62,13 @@ void add_drb(int is_gnb, unsigned char *integrity_key); 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, + int ciphering_algorithm, + const uint8_t *ciphering_key, + int integrity_algorithm, + const uint8_t *integrity_key); 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); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2a7aea5b07..0f2bdfeaac 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -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); @@ -880,10 +885,7 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context /* 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}; /* 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); LOG_I(NR_RRC, @@ -892,8 +894,11 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context 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. + */ + uint8_t security_mode = 0 | (ue_p->integrity_algorithm << 4); /* SRBs */ for (int srb_id = 1; srb_id < NR_NUM_SRB; srb_id++) { @@ -901,7 +906,14 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, true, security_mode, kRRCenc, kRRCint); } /* 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, + ue_p->integrity_algorithm, + kRRCint, + /* ciphering is enabled below, after encoding RRCReestablishment */ + 0, + NULL); /* 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 +924,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_mode = ue_p->ciphering_algorithm | (ue_p->integrity_algorithm << 4); + /* 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_mode, kRRCenc, kRRCint); + } } /// @brief Function tha processes RRCReestablishmentComplete message sent by the UE, after RRCReestasblishment request. @@ -933,9 +953,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 +983,12 @@ 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); + uint8_t kenc[NR_K_KEY_SIZE]; + uint8_t kint[NR_K_KEY_SIZE]; + nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kenc); + nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kint); + + nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true, ue_p->integrity_algorithm, kint, ue_p->ciphering_algorithm, kenc); } /* 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 +1913,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_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 6e3a617e02..34b580a995 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -631,14 +631,13 @@ 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_reestablishment(rrc->ue_id, srb_id, true, 0, NULL, 0, NULL); // 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, true, 0, NULL, NULL); // resume SRB1 rrc->Srb[srb_id] = RB_ESTABLISHED; break; @@ -1456,9 +1455,13 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, 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, + ue_rrc->integrityProtAlgorithm, + kRRCint, + ue_rrc->cipheringAlgorithm, + kRRCenc); } 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); @@ -1487,9 +1490,21 @@ 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); + /* re-establish */ + nr_pdcp_reestablishment(ue_rrc->ue_id, + DRB_id, + false, + has_integrity ? ue_rrc->integrityProtAlgorithm : 0, + kUPint, + has_ciphering ? ue_rrc->cipheringAlgorithm : 0, + kUPenc); } AssertFatal(drb->recoverPDCP == NULL, "recoverPDCP not yet implemented\n"); /* sdap-Config is included (SA mode) */