diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 87d95e89a..e825285c7 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -78,6 +78,8 @@ class usim_interface_rrc public: virtual void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg) = 0; virtual void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg) = 0; + virtual void store_keys_before_ho(const srslte::as_security_config_t& as_cfg) = 0; + virtual void restore_keys_from_failed_ho(srslte::as_security_config_t* as_cfg) = 0; }; // GW interface for NAS diff --git a/srsue/hdr/stack/upper/pcsc_usim.h b/srsue/hdr/stack/upper/pcsc_usim.h index e22d8299d..97bee2a6e 100644 --- a/srsue/hdr/stack/upper/pcsc_usim.h +++ b/srsue/hdr/stack/upper/pcsc_usim.h @@ -84,14 +84,16 @@ public: // RRC interface void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg); void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg); + void store_keys_before_ho(const srslte::as_security_config_t& as_ctx); + void restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx); private: srslte::log* log = nullptr; // User data // 3GPP 33.102 v10.0.0 Annex H - uint64_t imsi = 0; - uint64_t imei = 0; + uint64_t imsi = 0; + uint64_t imei = 0; std::string imsi_str; std::string imei_str; @@ -108,6 +110,11 @@ private: uint8_t k_enb_star[KEY_LEN] = {}; uint8_t auts[AKA_AUTS_LEN] = {}; + // Helpers to restore security context if HO fails + uint8_t old_k_enb[32] = {}; + uint8_t old_ncc = {}; + srslte::as_security_config_t old_as_ctx = {}; + uint32_t current_ncc = 0; bool initiated = false; diff --git a/srsue/hdr/stack/upper/usim.h b/srsue/hdr/stack/upper/usim.h index 85a8c10c4..2f8980e48 100644 --- a/srsue/hdr/stack/upper/usim.h +++ b/srsue/hdr/stack/upper/usim.h @@ -63,6 +63,8 @@ public: // RRC interface void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg); void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg); + void store_keys_before_ho(const srslte::as_security_config_t& as_ctx); + void restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx); private: auth_result_t gen_auth_res_milenage(uint8_t* rand, @@ -107,6 +109,11 @@ private: uint8_t k_enb[32] = {}; uint8_t k_enb_star[32] = {}; + // Helpers to restore security context if HO fails + uint8_t old_k_enb[32] = {}; + uint8_t old_ncc = {}; + srslte::as_security_config_t old_as_ctx = {}; + uint32_t current_ncc = 0; bool is_first_ncc = false; diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index cf861511b..135e481e7 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -367,8 +367,7 @@ proc_outcome_t rrc::si_acquire_proc::react(si_acq_timer_expired ev) *************************************/ rrc::serving_cell_config_proc::serving_cell_config_proc(rrc* parent_) : - rrc_ptr(parent_), - log_h(srslte::logmap::get("RRC")) + rrc_ptr(parent_), log_h(srslte::logmap::get("RRC")) {} /* @@ -762,8 +761,7 @@ void rrc::plmn_search_proc::then(const srslte::proc_state_t& result) const *************************************/ rrc::connection_request_proc::connection_request_proc(rrc* parent_) : - rrc_ptr(parent_), - log_h(srslte::logmap::get("RRC")) + rrc_ptr(parent_), log_h(srslte::logmap::get("RRC")) {} proc_outcome_t rrc::connection_request_proc::init(srslte::establishment_cause_t cause_, @@ -1195,7 +1193,6 @@ proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) // configure lower layers to consider the SCell(s), if configured, to be in deactivated state; rrc_ptr->phy->set_activation_deactivation_scell(0); - // 1> apply the default physical channel configuration as specified in 9.2.4; // Note: this is done by the MAC Reset procedure @@ -1241,7 +1238,7 @@ srslte::proc_outcome_t rrc::connection_reest_proc::cell_criteria() // Upon selecting a suitable E-UTRA cell, the UE shall: Info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n", rrc_ptr->t311.time_elapsed()); - + // Note: Not explicitly defined in the specs, but UE should apply SIB1 and SIB2 configuration in order to attempt // a PRACH to a different cell Info("Applying SIB2 configuration\n"); @@ -1503,6 +1500,7 @@ srslte::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc rrc_ptr->apply_rr_config_dedicated(&recfg_r8.rr_cfg_ded, true); } + rrc_ptr->usim->store_keys_before_ho(rrc_ptr->sec_cfg); // Security procedure int ncc = -1; if (recfg_r8.security_cfg_ho_present) { @@ -1582,7 +1580,7 @@ srslte::proc_outcome_t rrc::ho_proc::react(t304_expiry ev) Info("HO preparation timed out. Reverting RRC security config from source cell.\n"); // revert security settings from source cell for reestablishment according to Sec 5.3.7.4 - rrc_ptr->generate_as_keys(); + rrc_ptr->usim->restore_keys_from_failed_ho(&rrc_ptr->sec_cfg); rrc_ptr->pdcp->config_security_all(rrc_ptr->sec_cfg); diff --git a/srsue/src/stack/upper/pcsc_usim.cc b/srsue/src/stack/upper/pcsc_usim.cc index a28aa8f85..96523dc44 100644 --- a/srsue/src/stack/upper/pcsc_usim.cc +++ b/srsue/src/stack/upper/pcsc_usim.cc @@ -263,9 +263,7 @@ void pcsc_usim::generate_nas_keys(uint8_t* k_asme, RRC interface *******************************************************************************/ -void pcsc_usim::generate_as_keys(uint8_t* k_asme, - uint32_t count_ul, - srslte::as_security_config_t* sec_cfg) +void pcsc_usim::generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg) { if (!initiated) { ERROR("USIM not initiated!\n"); @@ -334,6 +332,24 @@ void pcsc_usim::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srsl k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data()); } +void pcsc_usim::store_keys_before_ho(const srslte::as_security_config_t& as_ctx) +{ + INFO("Storing AS Keys pre-handover. NCC=%d\n", current_ncc); + old_as_ctx = as_ctx; + old_ncc = current_ncc; + memcpy(old_k_enb, k_enb, 32); + return; +} + +void pcsc_usim::restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx) +{ + INFO("Restoring Keys from failed handover. NCC=%d\n", old_ncc); + *as_ctx = old_as_ctx; + current_ncc = old_ncc; + memcpy(k_enb, old_k_enb, 32); + return; +} + /******************************************************************************* Helpers *******************************************************************************/ diff --git a/srsue/src/stack/upper/usim.cc b/srsue/src/stack/upper/usim.cc index 48391e873..a6585ed10 100644 --- a/srsue/src/stack/upper/usim.cc +++ b/srsue/src/stack/upper/usim.cc @@ -284,6 +284,24 @@ void usim::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::a usim_log->info_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "HO K_RRC_int"); } +void usim::store_keys_before_ho(const srslte::as_security_config_t& as_ctx) +{ + usim_log->info("Storing AS Keys pre-handover. NCC=%d\n", current_ncc); + old_as_ctx = as_ctx; + old_ncc = current_ncc; + memcpy(old_k_enb, k_enb, 32); + return; +} + +void usim::restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx) +{ + usim_log->info("Restoring Keys from failed handover. NCC=%d\n", old_ncc); + *as_ctx = old_as_ctx; + current_ncc = old_ncc; + memcpy(k_enb, old_k_enb, 32); + return; +} + /******************************************************************************* Helpers *******************************************************************************/