handle security in re-establishment
This commit is contained in:
@@ -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?
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
+38
-11
@@ -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);
|
||||
|
||||
@@ -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) */
|
||||
|
||||
Reference in New Issue
Block a user