diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index 3595a0551..a8d7257cc 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -60,6 +60,10 @@ struct k_enb_context_t { uint32_t ncc; }; +struct k_gnb_context_t { + as_key_t sk_gnb; +}; + struct as_security_config_t { as_key_t k_rrc_int; as_key_t k_rrc_enc; diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 64e4a7367..2c3bcfb0e 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -280,6 +280,13 @@ public: virtual bool is_config_pending() = 0; }; +class usim_interface_rrc_nr +{ +public: + virtual void generate_nr_context(uint16_t sk_counter, srslte::as_security_config_t* sec_cfg) = 0; + virtual void update_nr_context(srslte::as_security_config_t* sec_cfg) = 0; +}; + // PDCP interface for RLC class pdcp_interface_rlc { diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index c1f75907f..b1e1ffece 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -55,6 +55,7 @@ public: pdcp_interface_rrc* pdcp_, gw_interface_rrc* gw_, rrc_eutra_interface_rrc_nr* rrc_eutra_, + usim_interface_rrc_nr* usim_, srslte::timer_handler* timers_, stack_interface_rrc* stack_, const rrc_nr_args_t& args_); @@ -110,6 +111,7 @@ public: uint32_t sk_counter_r15, bool nr_radio_bearer_cfg1_r15_present, asn1::dyn_octstring nr_radio_bearer_cfg1_r15); + void configure_sk_counter(uint16_t sk_counter); bool is_config_pending(); // STACK interface void cell_search_completed(const rrc_interface_phy_lte::cell_search_ret_t& cs_ret, const phy_cell_t& found_cell); @@ -131,6 +133,7 @@ private: pdcp_interface_rrc* pdcp = nullptr; gw_interface_rrc* gw = nullptr; rrc_eutra_interface_rrc_nr* rrc_eutra = nullptr; + usim_interface_rrc_nr* usim = nullptr; stack_interface_rrc* stack = nullptr; srslte::log_ref log_h; @@ -185,6 +188,7 @@ private: srslte::proc_outcome_t init(const bool endc_release_and_add_r15, const asn1::rrc_nr::rrc_recfg_s& rrc_recfg, const asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg, + bool sk_counter_r15_present, const uint32_t sk_counter_r15, const asn1::rrc_nr::radio_bearer_cfg_s& radio_bearer_cfg); srslte::proc_outcome_t step() { return srslte::proc_outcome_t::yield; } diff --git a/srsue/hdr/stack/upper/usim_base.h b/srsue/hdr/stack/upper/usim_base.h index 266659b05..b4e1db9ae 100644 --- a/srsue/hdr/stack/upper/usim_base.h +++ b/srsue/hdr/stack/upper/usim_base.h @@ -54,7 +54,7 @@ public: std::string reader; }; -class usim_base : public usim_interface_nas, public usim_interface_rrc +class usim_base : public usim_interface_nas, public usim_interface_rrc, public usim_interface_rrc_nr { public: usim_base(srslte::log* log_); @@ -92,6 +92,10 @@ public: void store_keys_before_ho(const srslte::as_security_config_t& as_ctx) final; void restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx) final; + // NR RRC interface + void generate_nr_context(uint16_t sk_counter, srslte::as_security_config_t* sec_cfg) final; + void update_nr_context(srslte::as_security_config_t* sec_cfg) final; + // Helpers std::string get_mcc_str(const uint8_t* imsi_vec); virtual std::string get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str) = 0; @@ -120,6 +124,7 @@ protected: // Current K_eNB context (K_eNB, NH and NCC) srslte::k_enb_context_t k_enb_ctx = {}; + srslte::k_gnb_context_t k_gnb_ctx = {}; // Helpers to restore security context if HO fails srslte::k_enb_context_t old_k_enb_ctx = {}; diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index de4315274..a2d603d98 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -12,6 +12,7 @@ #include "srsue/hdr/stack/rrc/rrc_nr.h" #include "srslte/common/security.h" +#include "srsue/hdr/stack/upper/usim.h" #define Error(fmt, ...) rrc_ptr->log_h->error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) #define Warning(fmt, ...) rrc_ptr->log_h->warning("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__) @@ -35,6 +36,7 @@ void rrc_nr::init(phy_interface_rrc_nr* phy_, pdcp_interface_rrc* pdcp_, gw_interface_rrc* gw_, rrc_eutra_interface_rrc_nr* rrc_eutra_, + usim_interface_rrc_nr* usim_, srslte::timer_handler* timers_, stack_interface_rrc* stack_, const rrc_nr_args_t& args_) @@ -45,6 +47,7 @@ void rrc_nr::init(phy_interface_rrc_nr* phy_, gw = gw_; mac = mac_; rrc_eutra = rrc_eutra_; + usim = usim_; timers = timers_; stack = stack_; args = args_; @@ -368,8 +371,12 @@ bool rrc_nr::rrc_reconfiguration(bool endc_release_and_add_r15, } log_rrc_message("RRC NR Reconfiguration", Rx, nr_radio_bearer_cfg1_r15, radio_bearer_cfg, "Radio Bearer Config R15"); - if (not conn_recfg_proc.launch( - endc_release_and_add_r15, rrc_recfg, cell_group_cfg, sk_counter_r15, radio_bearer_cfg)) { + if (not conn_recfg_proc.launch(endc_release_and_add_r15, + rrc_recfg, + cell_group_cfg, + sk_counter_r15_present, + sk_counter_r15, + radio_bearer_cfg)) { log_h->error("Unable to launch NR RRC configuration procedure\n"); return false; } else { @@ -436,6 +443,11 @@ void rrc_nr::phy_set_cells_to_meas(uint32_t carrier_freq_r15) fake_measurement_timer.run(); } +void rrc_nr::configure_sk_counter(uint16_t sk_counter) +{ + log_h->info("[NR] Configure new SK counter %d. Update Key for secondary gnb\n", sk_counter); + usim->generate_nr_context(sk_counter, &sec_cfg); +} bool rrc_nr::is_config_pending() { if (conn_recfg_proc.is_busy()) { @@ -600,6 +612,14 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) bool rrc_nr::apply_security_cfg(const security_cfg_s& security_cfg) { + + // TODO derive correct keys + if (security_cfg.key_to_use_present) { + if (security_cfg.key_to_use.value != security_cfg_s::key_to_use_opts::options::secondary) { + log_h->warning("Only secondary key supported yet\n"); + } + } + if (security_cfg.security_algorithm_cfg_present) { switch (security_cfg.security_algorithm_cfg.ciphering_algorithm) { case ciphering_algorithm_e::nea0: @@ -638,11 +658,8 @@ bool rrc_nr::apply_security_cfg(const security_cfg_s& security_cfg) break; } } + usim->update_nr_context(&sec_cfg); } - // TODO derive correct keys - if (security_cfg.key_to_use_present) { - } - // TODO derive correct keys // Apply security config for all known NR lcids for (auto& lcid : lcid_rb) { @@ -676,8 +693,9 @@ rrc_nr::connection_reconf_no_ho_proc::connection_reconf_no_ho_proc(rrc_nr* paren proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const bool endc_release_and_add_r15, const asn1::rrc_nr::rrc_recfg_s& rrc_recfg, - const asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg, - const uint32_t sk_counter_r15, + const asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg, + bool sk_counter_r15_present, + const uint32_t sk_counter_r15, const asn1::rrc_nr::radio_bearer_cfg_s& radio_bearer_cfg) { Info("Starting...\n"); @@ -687,6 +705,11 @@ proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const bool return proc_outcome_t::error; } + if (sk_counter_r15_present) { + Info("Applying Cell Group Cfg\n"); + rrc_ptr->configure_sk_counter((uint16_t)sk_counter_r15); + } + Info("Applying Radio Bearer Cfg\n"); if (!rrc_ptr->apply_radio_bearer_cfg(radio_bearer_cfg)) { return proc_outcome_t::error; diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index ddd8e8795..03b13e382 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -125,7 +125,8 @@ int ue_stack_lte::init(const stack_args_t& args_, srslte::logger* logger_) #ifdef HAVE_5GNR mac_nr_args_t mac_nr_args; mac_nr.init(mac_nr_args, nullptr, &rlc); - rrc_nr.init(nullptr, &mac_nr, &rlc, &pdcp, gw, &rrc, task_sched.get_timer_handler(), nullptr, args.rrc_nr); + rrc_nr.init( + nullptr, &mac_nr, &rlc, &pdcp, gw, &rrc, usim.get(), task_sched.get_timer_handler(), nullptr, args.rrc_nr); rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, &rrc_nr, args.rrc); #else rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, args.rrc); diff --git a/srsue/src/stack/ue_stack_nr.cc b/srsue/src/stack/ue_stack_nr.cc index 4647779b1..f044bd085 100644 --- a/srsue/src/stack/ue_stack_nr.cc +++ b/srsue/src/stack/ue_stack_nr.cc @@ -83,7 +83,8 @@ int ue_stack_nr::init(const stack_args_t& args_) rrc_args.log_hex_limit = args.log.rrc_hex_limit; rrc_args.coreless.drb_lcid = 4; rrc_args.coreless.ip_addr = "192.168.1.3"; - rrc->init(phy, mac.get(), rlc.get(), pdcp.get(), gw, nullptr, task_sched.get_timer_handler(), this, rrc_args); + rrc->init( + phy, mac.get(), rlc.get(), pdcp.get(), gw, nullptr, nullptr, task_sched.get_timer_handler(), this, rrc_args); rrc->init_core_less(); running = true; start(STACK_MAIN_THREAD_PRIO); diff --git a/srsue/src/stack/upper/usim_base.cc b/srsue/src/stack/upper/usim_base.cc index 015c96190..49aff9340 100644 --- a/srsue/src/stack/upper/usim_base.cc +++ b/srsue/src/stack/upper/usim_base.cc @@ -175,10 +175,10 @@ void usim_base::generate_as_keys(uint8_t* k_asme_, uint32_t count_ul, srslte::as k_enb_ctx.is_first_ncc = true; log->debug_hex(k_enb_ctx.k_enb.data(), 32, "Initial K_eNB"); - log->debug_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "K_RRC_enc"); - log->debug_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "K_RRC_enc"); - log->debug_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "K_RRC_int"); log->debug_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "K_RRC_int"); + log->debug_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "K_RRC_enc"); + log->debug_hex(sec_cfg->k_up_int.data(), sec_cfg->k_up_int.size(), "K_UP_int"); + log->debug_hex(sec_cfg->k_up_enc.data(), sec_cfg->k_up_enc.size(), "K_UP_enc"); } void usim_base::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg) @@ -265,4 +265,48 @@ void usim_base::restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx return; } +/* + * NR RRC Interface + */ + +void usim_base::generate_nr_context(uint16_t sk_counter, srslte::as_security_config_t* sec_cfg) +{ + if (!initiated) { + log->error("USIM not initiated!\n"); + return; + } + log->info("Generating Keys. SCG Counter %d\n", sk_counter); + + srslte::security_generate_sk_gnb(k_enb_ctx.k_enb.data(), k_gnb_ctx.sk_gnb.data(), sk_counter); + log->info_hex(k_gnb_ctx.sk_gnb.data(), 32, "k_sk_gnb"); + update_nr_context(sec_cfg); +} + +void usim_base::update_nr_context(srslte::as_security_config_t* sec_cfg) +{ + if (!initiated) { + log->error("USIM not initiated!\n"); + return; + } + log->info_hex(k_gnb_ctx.sk_gnb.data(), 32, "k_sk_gnb"); + // Generate K_rrc_enc and K_rrc_int + security_generate_k_nr_rrc(k_gnb_ctx.sk_gnb.data(), + sec_cfg->cipher_algo, + sec_cfg->integ_algo, + sec_cfg->k_rrc_enc.data(), + sec_cfg->k_rrc_int.data()); + + // Generate K_up_enc and K_up_int + security_generate_k_nr_up(k_gnb_ctx.sk_gnb.data(), + sec_cfg->cipher_algo, + sec_cfg->integ_algo, + sec_cfg->k_up_enc.data(), + sec_cfg->k_up_int.data()); + + log->debug_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "NR K_RRC_int"); + log->debug_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "NR K_RRC_enc"); + log->debug_hex(sec_cfg->k_up_int.data(), sec_cfg->k_up_int.size(), "NR K_UP_int"); + log->debug_hex(sec_cfg->k_up_enc.data(), sec_cfg->k_up_enc.size(), "NR K_UP_enc"); +} + } // namespace srsue