From d43448e8a13a07953c0d5659190e9503c3810251 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Tue, 12 May 2020 13:43:49 +0100 Subject: [PATCH] created security cfg handling class for rrc ue and refactor bearer_list handling --- lib/include/srslte/common/liblte_security.h | 14 +- lib/include/srslte/common/security.h | 30 +- lib/include/srslte/rrc/bearer_cfg.h | 6 +- lib/include/srslte/rrc/rrc_cfg_utils.h | 57 ++- lib/src/common/liblte_security.cc | 14 +- lib/src/common/security.cc | 30 +- srsenb/hdr/stack/rrc/rrc.h | 18 +- srsenb/hdr/stack/rrc/rrc_ue.h | 75 ++-- srsenb/src/stack/rrc/rrc.cc | 463 +++++++------------- srsenb/src/stack/rrc/rrc_mobility.cc | 8 +- srsenb/src/stack/rrc/rrc_ue.cc | 303 +++++++++---- 11 files changed, 498 insertions(+), 520 deletions(-) diff --git a/lib/include/srslte/common/liblte_security.h b/lib/include/srslte/common/liblte_security.h index 28a206d06..7f5eaadc2 100644 --- a/lib/include/srslte/common/liblte_security.h +++ b/lib/include/srslte/common/liblte_security.h @@ -179,13 +179,13 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8* // Enums // Structs // Functions -LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8* key, - uint32 count, - uint8 bearer, - uint8 direction, - uint8* msg, - uint32 msg_len, - uint8* mac); +LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8* msg, + uint32 msg_len, + uint8* mac); LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8* key, uint32 count, uint8 bearer, diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index 9e563d328..846f20c28 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -109,21 +109,21 @@ uint8_t security_generate_k_up(uint8_t* k_enb, /****************************************************************************** * Integrity Protection *****************************************************************************/ -uint8_t security_128_eia1(uint8_t* key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t* msg, - uint32_t msg_len, - uint8_t* mac); - -uint8_t security_128_eia2(uint8_t* key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t* msg, - uint32_t msg_len, - uint8_t* mac); +uint8_t security_128_eia1(const uint8_t* key, + uint32_t count, + uint32_t bearer, + uint8_t direction, + uint8_t* msg, + uint32_t msg_len, + uint8_t* mac); + +uint8_t security_128_eia2(const uint8_t* key, + uint32_t count, + uint32_t bearer, + uint8_t direction, + uint8_t* msg, + uint32_t msg_len, + uint8_t* mac); uint8_t security_128_eia3(uint8_t* key, uint32_t count, diff --git a/lib/include/srslte/rrc/bearer_cfg.h b/lib/include/srslte/rrc/bearer_cfg.h index be84157e9..51306ba02 100644 --- a/lib/include/srslte/rrc/bearer_cfg.h +++ b/lib/include/srslte/rrc/bearer_cfg.h @@ -29,11 +29,11 @@ namespace srslte { //! Apply toAddModList/toRelease diffs to SRBs void apply_srb_diff(asn1::rrc::srb_to_add_mod_list_l& src, - asn1::rrc::rr_cfg_ded_s& diff, + asn1::rrc::srb_to_add_mod_list_l& diff, asn1::rrc::srb_to_add_mod_list_l& target) { - if (diff.srb_to_add_mod_list_present) { - apply_addmodlist_diff(src, diff.srb_to_add_mod_list, target); + if (diff.size() > 0) { + apply_addmodlist_diff(src, diff, target); } else if (&target != &src) { target = src; } diff --git a/lib/include/srslte/rrc/rrc_cfg_utils.h b/lib/include/srslte/rrc/rrc_cfg_utils.h index 3e5ec110f..4380c176d 100644 --- a/lib/include/srslte/rrc/rrc_cfg_utils.h +++ b/lib/include/srslte/rrc/rrc_cfg_utils.h @@ -88,6 +88,33 @@ typename Container::const_iterator binary_find(const Container& c, IdType id) return (it == c.end() or asn1::rrc::get_rrc_obj_id(*it) != id) ? c.end() : it; } +/** + * Apply toAddModList changes + * @param src_list original list of rrc fields + * @param add_diff_list added/modified elements + * @param target_list resulting list. (Can be same as src_list) + */ +template +void apply_addmodlist_diff(AddModList& src_list, AddModList& add_diff_list, AddModList& target_list) +{ + // Shortcut for empty case + if (add_diff_list.size() == 0) { + if (&target_list != &src_list) { + target_list = src_list; + } + return; + } + // Sort Lists by ID + auto id_cmp_op = rrc_obj_id_list_cmp{}; + std::sort(src_list.begin(), src_list.end(), id_cmp_op); + std::sort(add_diff_list.begin(), add_diff_list.end(), id_cmp_op); + + AddModList l; + std::set_union( + add_diff_list.begin(), add_diff_list.end(), src_list.begin(), src_list.end(), std::back_inserter(l), id_cmp_op); + target_list = l; +} + /** * Apply toAddModList/toRemoveList changes * @param src_list original list of rrc fields @@ -126,36 +153,6 @@ void apply_addmodremlist_diff(AddModList& src_list, id_cmp_op); } -/** - * Apply toAddModList changes - * @param src_list original list of rrc fields - * @param add_diff_list added/modified elements - * @param target_list resulting list. (Can be same as src_list) - */ -template -void apply_addmodlist_diff(AddModList& src_list, AddModList& add_diff_list, AddModList& target_list) -{ - // Sort Lists by ID - auto id_cmp_op = rrc_obj_id_list_cmp{}; - std::sort(src_list.begin(), src_list.end(), id_cmp_op); - std::sort(add_diff_list.begin(), add_diff_list.end(), id_cmp_op); - - if (&target_list != &src_list) { - target_list.resize(0); - std::set_union(add_diff_list.begin(), - add_diff_list.end(), - src_list.begin(), - src_list.end(), - std::back_inserter(target_list), - id_cmp_op); - } else { - AddModList l; - std::set_union( - add_diff_list.begin(), add_diff_list.end(), src_list.begin(), src_list.end(), std::back_inserter(l), id_cmp_op); - target_list = l; - } -} - //! Update RRC field toAddModList template void apply_cfg_list_updates(List& src_list, diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index 7975ad5e2..6166d4ca8 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -626,13 +626,13 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8* 33.102 v10.0.0 Section 6.5.4 RFC4493 *********************************************************************/ -LIBLTE_ERROR_ENUM liblte_security_128_eia2(uint8* key, - uint32 count, - uint8 bearer, - uint8 direction, - uint8* msg, - uint32 msg_len, - uint8* mac) +LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key, + uint32 count, + uint8 bearer, + uint8 direction, + uint8* msg, + uint32 msg_len, + uint8* mac) { LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; uint8 M[msg_len + 8 + 16]; diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index d55eaa3d1..3423bc67a 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -105,33 +105,33 @@ uint8_t security_generate_k_up(uint8_t* k_enb, * Integrity Protection *****************************************************************************/ -uint8_t security_128_eia1(uint8_t* key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t* msg, - uint32_t msg_len, - uint8_t* mac) +uint8_t security_128_eia1(const uint8_t* key, + uint32_t count, + uint32_t bearer, + uint8_t direction, + uint8_t* msg, + uint32_t msg_len, + uint8_t* mac) { uint32_t msg_len_bits; uint32_t i; uint8_t* m_ptr; msg_len_bits = msg_len * 8; - m_ptr = snow3g_f9(key, count, bearer << 27, direction, msg, msg_len_bits); + m_ptr = snow3g_f9(const_cast(key), count, bearer << 27, direction, msg, msg_len_bits); for (i = 0; i < 4; i++) { mac[i] = m_ptr[i]; } return SRSLTE_SUCCESS; } -uint8_t security_128_eia2(uint8_t* key, - uint32_t count, - uint32_t bearer, - uint8_t direction, - uint8_t* msg, - uint32_t msg_len, - uint8_t* mac) +uint8_t security_128_eia2(const uint8_t* key, + uint32_t count, + uint32_t bearer, + uint8_t direction, + uint8_t* msg, + uint32_t msg_len, + uint8_t* mac) { return liblte_security_128_eia2(key, count, bearer, direction, msg, msg_len, mac); } diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index a3b1a97eb..4c30c8be9 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -136,7 +136,7 @@ private: void send_connection_release(); void send_connection_reest_rej(); void send_connection_reconf(srslte::unique_byte_buffer_t sdu); - void send_connection_reconf_new_bearer(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e); + void send_connection_reconf_new_bearer(); void send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu); void send_security_mode_command(); void send_ue_cap_enquiry(); @@ -149,10 +149,10 @@ private: void handle_security_mode_complete(asn1::rrc::security_mode_complete_s* msg); void handle_security_mode_failure(asn1::rrc::security_mode_fail_s* msg); bool handle_ue_cap_info(asn1::rrc::ue_cap_info_s* msg); + void handle_ue_init_ctxt_setup_req(const asn1::s1ap::init_context_setup_request_s& msg); + bool handle_ue_ctxt_mod_req(const asn1::s1ap::ue_context_mod_request_s& msg); void set_bitrates(const asn1::s1ap::ue_aggregate_maximum_bitrate_s& rates); - void set_security_capabilities(const asn1::s1ap::ue_security_cap_s& caps); - void set_security_key(const asn1::fixed_bitstring<256, false, true>& key); bool setup_erabs(const asn1::s1ap::erab_to_be_setup_list_ctxt_su_req_l& e); bool setup_erabs(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e); @@ -169,7 +169,6 @@ private: int get_ri(uint32_t m_ri, uint16_t* ri_idx); bool is_allocated() const; - bool select_security_algorithms(); void send_dl_ccch(asn1::rrc::dl_ccch_msg_s* dl_ccch_msg); bool send_dl_dcch(const asn1::rrc::dl_dcch_msg_s* dl_dcch_msg, srslte::unique_byte_buffer_t pdu = srslte::unique_byte_buffer_t()); @@ -188,8 +187,7 @@ private: srslte::timer_handler::unique_timer activity_timer; // cached for ease of context transfer - asn1::rrc::rrc_conn_recfg_s last_rrc_conn_recfg; - asn1::rrc::security_algorithm_cfg_s last_security_mode_cmd; + asn1::rrc::rrc_conn_recfg_s last_rrc_conn_recfg; asn1::rrc::establishment_cause_e establishment_cause; @@ -207,11 +205,8 @@ private: std::map srbs; std::map drbs; - uint8_t k_enb[32]; // Provided by MME - srslte::as_security_config_t sec_cfg = {}; - asn1::s1ap::ue_aggregate_maximum_bitrate_s bitrates; - asn1::s1ap::ue_security_cap_s security_capabilities; + security_cfg_handler ue_security_cfg; bool eutra_capabilities_unpacked = false; asn1::rrc::ue_eutra_cap_s eutra_capabilities; srslte::rrc_ue_capabilities_t ue_capabilities; @@ -284,9 +279,6 @@ private: void config_mac(); void parse_ul_dcch(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu); void parse_ul_ccch(uint16_t rnti, srslte::unique_byte_buffer_t pdu); - void configure_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg); - void enable_integrity(uint16_t rnti, uint32_t lcid); - void enable_encryption(uint16_t rnti, uint32_t lcid); srslte::byte_buffer_t byte_buf_paging; diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index f9f6a6808..52b5f8148 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -29,54 +29,63 @@ namespace srsenb { +class security_cfg_handler +{ +public: + explicit security_cfg_handler(const rrc_cfg_t& cfg_) : cfg(&cfg_) {} + + bool set_security_capabilities(const asn1::s1ap::ue_security_cap_s& caps); + void set_security_key(const asn1::fixed_bitstring<256, false, true>& key); + + asn1::rrc::security_algorithm_cfg_s get_security_algorithm_cfg(); + const srslte::as_security_config_t& get_as_sec_cfg() const { return sec_cfg; } + +private: + srslte::log_ref log_h{"RRC"}; + const rrc_cfg_t* cfg; + asn1::s1ap::ue_security_cap_s security_capabilities; + uint8_t k_enb[32] = {}; // Provided by MME + srslte::as_security_config_t sec_cfg = {}; +}; + class bearer_handler { public: struct erab_t { - uint8_t id; + uint8_t id = 0; asn1::s1ap::erab_level_qos_params_s qos_params; asn1::bounded_bitstring<1, 160, true, true> address; - uint32_t teid_out; - uint32_t teid_in; + uint32_t teid_out = 0; + uint32_t teid_in = 0; }; - bearer_handler(uint16_t rnti_, - const rrc_cfg_t& cfg_, - pdcp_interface_rrc* pdcp_, - rlc_interface_rrc* rlc_, - mac_interface_rrc* mac_, - gtpu_interface_rrc* gtpu_, - sched_interface::ue_cfg_t& ue_cfg_); - - void setup_srb(uint8_t srb_id); - int setup_erab(uint8_t id, - const asn1::s1ap::erab_level_qos_params_s& qos, - const asn1::bounded_bitstring<1, 160, true, true>& addr, - uint32_t teid_out, - const asn1::unbounded_octstring* nas_pdu); + bearer_handler(uint16_t rnti_, const rrc_cfg_t& cfg_, gtpu_interface_rrc* gtpu_); + + void add_srb(uint8_t srb_id); + int add_erab(uint8_t erab_id, + const asn1::s1ap::erab_level_qos_params_s& qos, + const asn1::bounded_bitstring<1, 160, true, true>& addr, + uint32_t teid_out, + const asn1::unbounded_octstring* nas_pdu); void release_erab(uint8_t erab_id); void release_erabs(); - void handle_rrc_setup(asn1::rrc::rrc_conn_setup_r8_ies_s* msg); - void handle_rrc_reest(asn1::rrc::rrc_conn_reest_r8_ies_s* msg); - void handle_rrc_reconf(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg); - void handle_rrc_reconf_complete(); + bool fill_rr_cfg_ded(asn1::rrc::rr_cfg_ded_s& msg); + void rr_ded_cfg_complete(); + + // Methods to apply bearer updates + void apply_mac_bearer_updates(mac_interface_rrc* mac, sched_interface::ue_cfg_t* sched_ue_cfg); + void apply_pdcp_bearer_updates(pdcp_interface_rrc* pdcp, const security_cfg_handler& ue_sec_cfg); + void apply_rlc_bearer_updates(rlc_interface_rrc* rlc); + void fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg); const std::map& get_erabs() const { return erabs; } private: - void fill_and_apply_bearer_updates(asn1::rrc::rr_cfg_ded_s& msg); - void fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg); - - srslte::log_ref log_h{"RRC"}; - uint16_t rnti; - const rrc_cfg_t* cfg; - pdcp_interface_rrc* pdcp; - rlc_interface_rrc* rlc; - mac_interface_rrc* mac; - gtpu_interface_rrc* gtpu; - sched_interface::ue_cfg_t* sched_ue_cfg; - srslte::byte_buffer_pool* pool = nullptr; + srslte::log_ref log_h{"RRC"}; + uint16_t rnti; + const rrc_cfg_t* cfg; + gtpu_interface_rrc* gtpu; std::map > erab_info_list; std::map erabs; diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index af46f0e34..2808a4c8d 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -280,73 +280,12 @@ bool rrc::setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_requ return false; } - if (msg.protocol_ies.add_cs_fallback_ind_present) { - rrc_log->warning("Not handling AdditionalCSFallbackIndicator\n"); - } - if (msg.protocol_ies.csg_membership_status_present) { - rrc_log->warning("Not handling CSGMembershipStatus\n"); - } - if (msg.protocol_ies.gummei_id_present) { - rrc_log->warning("Not handling GUMMEI_ID\n"); - } - if (msg.protocol_ies.ho_restrict_list_present) { - rrc_log->warning("Not handling HandoverRestrictionList\n"); - } - if (msg.protocol_ies.management_based_mdt_allowed_present) { - rrc_log->warning("Not handling ManagementBasedMDTAllowed\n"); - } - if (msg.protocol_ies.management_based_mdtplmn_list_present) { - rrc_log->warning("Not handling ManagementBasedMDTPLMNList\n"); - } - if (msg.protocol_ies.mme_ue_s1ap_id_minus2_present) { - rrc_log->warning("Not handling MME_UE_S1AP_ID_2\n"); - } - if (msg.protocol_ies.registered_lai_present) { - rrc_log->warning("Not handling RegisteredLAI\n"); - } - if (msg.protocol_ies.srvcc_operation_possible_present) { - rrc_log->warning("Not handling SRVCCOperationPossible\n"); - } - if (msg.protocol_ies.subscriber_profile_idfor_rfp_present) { - rrc_log->warning("Not handling SubscriberProfileIDforRFP\n"); - } - if (msg.protocol_ies.trace_activation_present) { - rrc_log->warning("Not handling TraceActivation\n"); - } - if (msg.protocol_ies.ue_radio_cap_present) { - rrc_log->warning("Not handling UERadioCapability\n"); - } - - // UEAggregateMaximumBitrate - user_it->second->set_bitrates(msg.protocol_ies.ueaggregate_maximum_bitrate.value); - - // UESecurityCapabilities - user_it->second->set_security_capabilities(msg.protocol_ies.ue_security_cap.value); - - // SecurityKey - user_it->second->set_security_key(msg.protocol_ies.security_key.value); - - // CSFB - if (msg.protocol_ies.cs_fallback_ind_present) { - if (msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_required or - msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_high_prio) { - user_it->second->is_csfb = true; - } - } - - // Send RRC security mode command - user_it->second->send_security_mode_command(); - - // Setup E-RABs - user_it->second->setup_erabs(msg.protocol_ies.erab_to_be_setup_list_ctxt_su_req.value); - + user_it->second->handle_ue_init_ctxt_setup_req(msg); return true; } bool rrc::modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) { - bool err = false; - rrc_log->info("Modifying context for 0x%x\n", rnti); auto user_it = users.find(rnti); @@ -355,54 +294,7 @@ bool rrc::modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request return false; } - if (msg.protocol_ies.cs_fallback_ind_present) { - if (msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_required || - msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_high_prio) { - /* Remember that we are in a CSFB right now */ - user_it->second->is_csfb = true; - } - } - - if (msg.protocol_ies.add_cs_fallback_ind_present) { - rrc_log->warning("Not handling AdditionalCSFallbackIndicator\n"); - err = true; - } - if (msg.protocol_ies.csg_membership_status_present) { - rrc_log->warning("Not handling CSGMembershipStatus\n"); - err = true; - } - if (msg.protocol_ies.registered_lai_present) { - rrc_log->warning("Not handling RegisteredLAI\n"); - } - if (msg.protocol_ies.subscriber_profile_idfor_rfp_present) { - rrc_log->warning("Not handling SubscriberProfileIDforRFP\n"); - err = true; - } - - if (err) { - // maybe pass a cause value? - return false; - } - - // UEAggregateMaximumBitrate - if (msg.protocol_ies.ueaggregate_maximum_bitrate_present) { - user_it->second->set_bitrates(msg.protocol_ies.ueaggregate_maximum_bitrate.value); - } - - // UESecurityCapabilities - if (msg.protocol_ies.ue_security_cap_present) { - user_it->second->set_security_capabilities(msg.protocol_ies.ue_security_cap.value); - } - - // SecurityKey - if (msg.protocol_ies.security_key_present) { - user_it->second->set_security_key(msg.protocol_ies.security_key.value); - - // Send RRC security mode command ?? - user_it->second->send_security_mode_command(); - } - - return true; + return user_it->second->handle_ue_ctxt_mod_req(msg); } bool rrc::setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) @@ -905,21 +797,6 @@ void rrc::configure_mbsfn_sibs(sib_type2_s* sib2_, sib_type13_r9_s* sib13_) mac->write_mcch(sib2_, sib13_, &mcch); } -void rrc::configure_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg) -{ - pdcp->config_security(rnti, lcid, sec_cfg); -} - -void rrc::enable_integrity(uint16_t rnti, uint32_t lcid) -{ - pdcp->enable_integrity(rnti, lcid); -} - -void rrc::enable_encryption(uint16_t rnti, uint32_t lcid) -{ - pdcp->enable_encryption(rnti, lcid); -} - /******************************************************************************* RRC run tti method *******************************************************************************/ @@ -986,7 +863,8 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_, const sched_interface::ue_cfg_t& sch current_sched_ue_cfg(sched_ue_cfg), phy_rrc_dedicated_list(sched_ue_cfg.supported_cc_list.size()), cell_ded_list(parent->cfg, *outer_rrc->pucch_res_list, *outer_rrc->cell_common_list), - bearer_list(rnti_, parent->cfg, parent->pdcp, parent->rlc, parent->mac, parent->gtpu, current_sched_ue_cfg) + bearer_list(rnti_, parent->cfg, parent->gtpu), + ue_security_cfg(parent->cfg) { if (current_sched_ue_cfg.supported_cc_list.empty() or not current_sched_ue_cfg.supported_cc_list[0].active) { parent->rrc_log->warning("No PCell set. Picking eNBccIdx=0 as PCell\n"); @@ -1220,6 +1098,9 @@ void rrc::ue::handle_rrc_con_setup_complete(rrc_conn_setup_complete_s* msg, srsl // Acknowledge Dedicated Configuration parent->mac->phy_config_enabled(rnti, true); + // Flag completion of RadioResource Configuration + bearer_list.rr_ded_cfg_complete(); + asn1::s1ap::rrc_establishment_cause_e s1ap_cause; s1ap_cause.value = (asn1::s1ap::rrc_establishment_cause_opts::options)establishment_cause.value; if (has_tmsi) { @@ -1249,7 +1130,13 @@ void rrc::ue::handle_rrc_reconf_complete(rrc_conn_recfg_complete_s* msg, srslte: } parent->mac->ue_cfg(rnti, ¤t_sched_ue_cfg); - bearer_list.handle_rrc_reconf_complete(); + bearer_list.apply_mac_bearer_updates(parent->mac, ¤t_sched_ue_cfg); + + // Acknowledge Dedicated Configuration + parent->mac->phy_config_enabled(rnti, true); + + // Flag completion of RadioResource Configuration + bearer_list.rr_ded_cfg_complete(); } else { parent->rrc_log->error("Expected RRCReconfigurationComplete with transaction ID: %d, got %d\n", last_rrc_conn_recfg.rrc_transaction_id, @@ -1260,7 +1147,8 @@ void rrc::ue::handle_rrc_reconf_complete(rrc_conn_recfg_complete_s* msg, srslte: void rrc::ue::handle_security_mode_complete(security_mode_complete_s* msg) { parent->rrc_log->info("SecurityModeComplete transaction ID: %d\n", msg->rrc_transaction_id); - parent->enable_encryption(rnti, RB_ID_SRB1); + + parent->pdcp->enable_encryption(rnti, RB_ID_SRB1); } void rrc::ue::handle_security_mode_failure(security_mode_fail_s* msg) @@ -1299,43 +1187,108 @@ bool rrc::ue::handle_ue_cap_info(ue_cap_info_s* msg) // parent->s1ap->ue_capabilities(rnti, &eutra_capabilities); } -void rrc::ue::set_bitrates(const asn1::s1ap::ue_aggregate_maximum_bitrate_s& rates) +void rrc::ue::handle_ue_init_ctxt_setup_req(const asn1::s1ap::init_context_setup_request_s& msg) { - bitrates = rates; -} + if (msg.protocol_ies.add_cs_fallback_ind_present) { + parent->rrc_log->warning("Not handling AdditionalCSFallbackIndicator\n"); + } + if (msg.protocol_ies.csg_membership_status_present) { + parent->rrc_log->warning("Not handling CSGMembershipStatus\n"); + } + if (msg.protocol_ies.gummei_id_present) { + parent->rrc_log->warning("Not handling GUMMEI_ID\n"); + } + if (msg.protocol_ies.ho_restrict_list_present) { + parent->rrc_log->warning("Not handling HandoverRestrictionList\n"); + } + if (msg.protocol_ies.management_based_mdt_allowed_present) { + parent->rrc_log->warning("Not handling ManagementBasedMDTAllowed\n"); + } + if (msg.protocol_ies.management_based_mdtplmn_list_present) { + parent->rrc_log->warning("Not handling ManagementBasedMDTPLMNList\n"); + } + if (msg.protocol_ies.mme_ue_s1ap_id_minus2_present) { + parent->rrc_log->warning("Not handling MME_UE_S1AP_ID_2\n"); + } + if (msg.protocol_ies.registered_lai_present) { + parent->rrc_log->warning("Not handling RegisteredLAI\n"); + } + if (msg.protocol_ies.srvcc_operation_possible_present) { + parent->rrc_log->warning("Not handling SRVCCOperationPossible\n"); + } + if (msg.protocol_ies.subscriber_profile_idfor_rfp_present) { + parent->rrc_log->warning("Not handling SubscriberProfileIDforRFP\n"); + } + if (msg.protocol_ies.trace_activation_present) { + parent->rrc_log->warning("Not handling TraceActivation\n"); + } + if (msg.protocol_ies.ue_radio_cap_present) { + parent->rrc_log->warning("Not handling UERadioCapability\n"); + } -void rrc::ue::set_security_capabilities(const asn1::s1ap::ue_security_cap_s& caps) -{ - security_capabilities = caps; + set_bitrates(msg.protocol_ies.ueaggregate_maximum_bitrate.value); + ue_security_cfg.set_security_capabilities(msg.protocol_ies.ue_security_cap.value); + ue_security_cfg.set_security_key(msg.protocol_ies.security_key.value); + + // CSFB + if (msg.protocol_ies.cs_fallback_ind_present) { + if (msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_required or + msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_high_prio) { + is_csfb = true; + } + } + + // Send RRC security mode command + send_security_mode_command(); + + // Setup E-RABs + setup_erabs(msg.protocol_ies.erab_to_be_setup_list_ctxt_su_req.value); } -void rrc::ue::set_security_key(const asn1::fixed_bitstring<256, false, true>& key) +bool rrc::ue::handle_ue_ctxt_mod_req(const asn1::s1ap::ue_context_mod_request_s& msg) { - for (uint32_t i = 0; i < key.nof_octets(); ++i) { - k_enb[i] = key.data()[key.nof_octets() - 1 - i]; + if (msg.protocol_ies.cs_fallback_ind_present) { + if (msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_required || + msg.protocol_ies.cs_fallback_ind.value.value == asn1::s1ap::cs_fallback_ind_opts::cs_fallback_high_prio) { + /* Remember that we are in a CSFB right now */ + is_csfb = true; + } } - parent->rrc_log->info_hex(k_enb, 32, "Key eNodeB (k_enb)"); - // Selects security algorithms (cipher_algo and integ_algo) based on capabilities and config preferences - select_security_algorithms(); - parent->rrc_log->info( - "Selected security algorithms EEA: EEA%d EIA: EIA%d\n", sec_cfg.cipher_algo, sec_cfg.integ_algo); + if (msg.protocol_ies.add_cs_fallback_ind_present) { + parent->rrc_log->warning("Not handling AdditionalCSFallbackIndicator\n"); + } + if (msg.protocol_ies.csg_membership_status_present) { + parent->rrc_log->warning("Not handling CSGMembershipStatus\n"); + } + if (msg.protocol_ies.registered_lai_present) { + parent->rrc_log->warning("Not handling RegisteredLAI\n"); + } + if (msg.protocol_ies.subscriber_profile_idfor_rfp_present) { + parent->rrc_log->warning("Not handling SubscriberProfileIDforRFP\n"); + } - // Generate K_rrc_enc and K_rrc_int - srslte::security_generate_k_rrc( - k_enb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_rrc_enc.data(), sec_cfg.k_rrc_int.data()); + // UEAggregateMaximumBitrate + if (msg.protocol_ies.ueaggregate_maximum_bitrate_present) { + set_bitrates(msg.protocol_ies.ueaggregate_maximum_bitrate.value); + } + + if (msg.protocol_ies.ue_security_cap_present) { + ue_security_cfg.set_security_capabilities(msg.protocol_ies.ue_security_cap.value); + } - // Generate K_up_enc and K_up_int - security_generate_k_up( - k_enb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_up_enc.data(), sec_cfg.k_up_int.data()); + if (msg.protocol_ies.security_key_present) { + ue_security_cfg.set_security_key(msg.protocol_ies.security_key.value); - parent->configure_security(rnti, RB_ID_SRB1, sec_cfg); + send_security_mode_command(); + } - parent->enable_integrity(rnti, RB_ID_SRB1); + return true; +} - parent->rrc_log->info_hex(sec_cfg.k_rrc_enc.data(), 32, "RRC Encryption Key (k_rrc_enc)"); - parent->rrc_log->info_hex(sec_cfg.k_rrc_int.data(), 32, "RRC Integrity Key (k_rrc_int)"); - parent->rrc_log->info_hex(sec_cfg.k_up_enc.data(), 32, "UP Encryption Key (k_up_enc)"); +void rrc::ue::set_bitrates(const asn1::s1ap::ue_aggregate_maximum_bitrate_s& rates) +{ + bitrates = rates; } bool rrc::ue::setup_erabs(const asn1::s1ap::erab_to_be_setup_list_ctxt_su_req_l& e) @@ -1356,7 +1309,7 @@ bool rrc::ue::setup_erabs(const asn1::s1ap::erab_to_be_setup_list_ctxt_su_req_l& uint32_t teid_out; uint8_to_uint32(erab.gtp_teid.data(), &teid_out); const asn1::unbounded_octstring* nas_pdu = erab.nas_pdu_present ? &erab.nas_pdu : nullptr; - bearer_list.setup_erab(erab.erab_id, erab.erab_level_qos_params, erab.transport_layer_address, teid_out, nas_pdu); + bearer_list.add_erab(erab.erab_id, erab.erab_level_qos_params, erab.transport_layer_address, teid_out, nas_pdu); } return true; } @@ -1378,13 +1331,13 @@ bool rrc::ue::setup_erabs(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_ uint32_t teid_out; uint8_to_uint32(erab.gtp_teid.data(), &teid_out); - bearer_list.setup_erab( + bearer_list.add_erab( erab.erab_id, erab.erab_level_qos_params, erab.transport_layer_address, teid_out, &erab.nas_pdu); } // Work in progress notify_s1ap_ue_erab_setup_response(e); - send_connection_reconf_new_bearer(e); + send_connection_reconf_new_bearer(); return true; } @@ -1459,7 +1412,7 @@ void rrc::ue::send_connection_reject() void rrc::ue::send_connection_setup(bool is_setup) { // (Re-)Establish SRB1 - bearer_list.setup_srb(1); + bearer_list.add_srb(1); dl_ccch_msg_s dl_ccch_msg; dl_ccch_msg.msg.set_c1(); @@ -1477,6 +1430,9 @@ void rrc::ue::send_connection_setup(bool is_setup) rr_cfg = &dl_ccch_msg.msg.c1().rrc_conn_reest().crit_exts.c1().rrc_conn_reest_r8().rr_cfg_ded; } + // drbsToAddModList/srbsToAddModList/drbsToReleaseList + bearer_list.fill_rr_cfg_ded(*rr_cfg); + // mac-MainConfig rr_cfg->mac_main_cfg_present = true; mac_main_cfg_s* mac_cfg = &rr_cfg->mac_main_cfg.set_explicit_value(); @@ -1571,18 +1527,18 @@ void rrc::ue::send_connection_setup(bool is_setup) current_sched_ue_cfg.pucch_cfg.N_pucch_1 = sib2.rr_cfg_common.pucch_cfg_common.n1_pucch_an; current_sched_ue_cfg.dl_ant_info = srslte::make_ant_info_ded(phy_cfg->ant_info.explicit_value()); - // Configure MAC + RLC + PDCP + // Configure MAC if (is_setup) { // In case of RRC Connection Setup message (Msg4), we need to resolve the contention by sending a ConRes CE parent->mac->ue_set_crnti(rnti, rnti, ¤t_sched_ue_cfg); - - bearer_list.handle_rrc_setup(&dl_ccch_msg.msg.c1().rrc_conn_setup().crit_exts.c1().rrc_conn_setup_r8()); } else { parent->mac->ue_cfg(rnti, ¤t_sched_ue_cfg); - - bearer_list.handle_rrc_reest(&dl_ccch_msg.msg.c1().rrc_conn_reest().crit_exts.c1().rrc_conn_reest_r8()); } + // Add SRBs/DRBs, and configure RLC+PDCP + bearer_list.apply_pdcp_bearer_updates(parent->pdcp, ue_security_cfg); + bearer_list.apply_rlc_bearer_updates(parent->rlc); + // Configure PHY layer apply_setup_phy_config_dedicated(*phy_cfg); // It assumes SCell has not been set before parent->mac->phy_config_enabled(rnti, false); @@ -1602,12 +1558,11 @@ void rrc::ue::send_connection_reest() void rrc::ue::send_connection_release() { dl_dcch_msg_s dl_dcch_msg; - dl_dcch_msg.msg.set_c1().set_rrc_conn_release(); - dl_dcch_msg.msg.c1().rrc_conn_release().rrc_transaction_id = (uint8_t)((transaction_id++) % 4); - dl_dcch_msg.msg.c1().rrc_conn_release().crit_exts.set_c1().set_rrc_conn_release_r8(); - dl_dcch_msg.msg.c1().rrc_conn_release().crit_exts.c1().rrc_conn_release_r8().release_cause = release_cause_e::other; + auto& rrc_release = dl_dcch_msg.msg.set_c1().set_rrc_conn_release(); + rrc_release.rrc_transaction_id = (uint8_t)((transaction_id++) % 4); + rrc_conn_release_r8_ies_s& rel_ies = rrc_release.crit_exts.set_c1().set_rrc_conn_release_r8(); + rel_ies.release_cause = release_cause_e::other; if (is_csfb) { - rrc_conn_release_r8_ies_s& rel_ies = dl_dcch_msg.msg.c1().rrc_conn_release().crit_exts.c1().rrc_conn_release_r8(); rel_ies.redirected_carrier_info_present = true; rel_ies.redirected_carrier_info.set_geran(); rel_ies.redirected_carrier_info.geran() = parent->sib7.carrier_freqs_info_list[0].carrier_freqs; @@ -1672,14 +1627,16 @@ void rrc::ue::send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu) void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) { // Setup SRB2 - bearer_list.setup_srb(2); + bearer_list.add_srb(2); dl_dcch_msg_s dl_dcch_msg; dl_dcch_msg.msg.set_c1().set_rrc_conn_recfg().crit_exts.set_c1().set_rrc_conn_recfg_r8(); dl_dcch_msg.msg.c1().rrc_conn_recfg().rrc_transaction_id = (uint8_t)((transaction_id++) % 4); rrc_conn_recfg_r8_ies_s* conn_reconf = &dl_dcch_msg.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); - conn_reconf->rr_cfg_ded_present = true; + + // Add DRBs/SRBs + conn_reconf->rr_cfg_ded_present = bearer_list.fill_rr_cfg_ded(conn_reconf->rr_cfg_ded); conn_reconf->rr_cfg_ded.phys_cfg_ded_present = true; phys_cfg_ded_s* phy_cfg = &conn_reconf->rr_cfg_ded.phys_cfg_ded; @@ -1743,19 +1700,12 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) parent->mac->ue_cfg(rnti, ¤t_sched_ue_cfg); parent->mac->phy_config_enabled(rnti, false); - // Fill Reconf message, and setup SRB2/DRBs in PDCP and RLC - bearer_list.handle_rrc_reconf(conn_reconf); + // setup SRB2/DRBs in PDCP and RLC + bearer_list.apply_pdcp_bearer_updates(parent->pdcp, ue_security_cfg); + bearer_list.apply_rlc_bearer_updates(parent->rlc); - // Configure SRB2 security - parent->pdcp->config_security(rnti, 2, sec_cfg); - parent->pdcp->enable_integrity(rnti, 2); - parent->pdcp->enable_encryption(rnti, 2); - - for (const drb_to_add_mod_s& drb : conn_reconf->rr_cfg_ded.drb_to_add_mod_list) { - parent->pdcp->config_security(rnti, drb.lc_ch_id, sec_cfg); - parent->pdcp->enable_integrity(rnti, drb.lc_ch_id); - parent->pdcp->enable_encryption(rnti, drb.lc_ch_id); - } + // Add pending NAS info + bearer_list.fill_pending_nas_info(conn_reconf); if (mobility_handler != nullptr) { mobility_handler->fill_conn_recfg_msg(conn_reconf); @@ -1933,18 +1883,23 @@ int rrc::ue::fill_scell_to_addmod_list(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_ return SRSLTE_SUCCESS; } -void rrc::ue::send_connection_reconf_new_bearer(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e) +void rrc::ue::send_connection_reconf_new_bearer() { - srslte::unique_byte_buffer_t pdu = srslte::allocate_unique_buffer(*pool); - dl_dcch_msg_s dl_dcch_msg; dl_dcch_msg.msg.set_c1().set_rrc_conn_recfg().crit_exts.set_c1().set_rrc_conn_recfg_r8(); dl_dcch_msg.msg.c1().rrc_conn_recfg().rrc_transaction_id = (uint8_t)((transaction_id++) % 4); rrc_conn_recfg_r8_ies_s* conn_reconf = &dl_dcch_msg.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); - bearer_list.handle_rrc_reconf(conn_reconf); + conn_reconf->rr_cfg_ded_present = bearer_list.fill_rr_cfg_ded(conn_reconf->rr_cfg_ded); + + // Setup new bearer + bearer_list.apply_pdcp_bearer_updates(parent->pdcp, ue_security_cfg); + bearer_list.apply_rlc_bearer_updates(parent->rlc); + // Add pending NAS info + bearer_list.fill_pending_nas_info(conn_reconf); + if (conn_reconf->rr_cfg_ded_present or conn_reconf->ded_info_nas_list_present) { - send_dl_dcch(&dl_dcch_msg, std::move(pdu)); + send_dl_dcch(&dl_dcch_msg); } } @@ -1954,13 +1909,12 @@ void rrc::ue::send_security_mode_command() security_mode_cmd_s* comm = &dl_dcch_msg.msg.set_c1().set_security_mode_cmd(); comm->rrc_transaction_id = (uint8_t)((transaction_id++) % 4); - // TODO: select these based on UE capabilities and preference order - comm->crit_exts.set_c1().set_security_mode_cmd_r8(); - comm->crit_exts.c1().security_mode_cmd_r8().security_cfg_smc.security_algorithm_cfg.ciphering_algorithm = - (ciphering_algorithm_r12_e::options)sec_cfg.cipher_algo; - comm->crit_exts.c1().security_mode_cmd_r8().security_cfg_smc.security_algorithm_cfg.integrity_prot_algorithm = - (security_algorithm_cfg_s::integrity_prot_algorithm_e_::options)sec_cfg.integ_algo; - last_security_mode_cmd = comm->crit_exts.c1().security_mode_cmd_r8().security_cfg_smc.security_algorithm_cfg; + comm->crit_exts.set_c1().set_security_mode_cmd_r8().security_cfg_smc.security_algorithm_cfg = + ue_security_cfg.get_security_algorithm_cfg(); + + // Setup SRB1 security/integrity. Encryption is set on completion + parent->pdcp->enable_integrity(rnti, RB_ID_SRB1); + parent->pdcp->config_security(rnti, RB_ID_SRB1, ue_security_cfg.get_as_sec_cfg()); send_dl_dcch(&dl_dcch_msg); } @@ -1988,129 +1942,6 @@ void rrc::ue::handle_ho_preparation_complete(bool is_success, srslte::unique_byt /********************** HELPERS ***************************/ -bool rrc::ue::select_security_algorithms() -{ - // Each position in the bitmap represents an encryption algorithm: - // “all bits equal to 0” – UE supports no other algorithm than EEA0, - // “first bit” – 128-EEA1, - // “second bit” – 128-EEA2, - // “third bit” – 128-EEA3, - // other bits reserved for future use. Value ‘1’ indicates support and value - // ‘0’ indicates no support of the algorithm. - // Algorithms are defined in TS 33.401 [15]. - // Note: information missing - - bool enc_algo_found = false; - bool integ_algo_found = false; - - for (auto& cipher_item : parent->cfg.eea_preference_list) { - auto& v = security_capabilities.encryption_algorithms; - switch (cipher_item) { - case srslte::CIPHERING_ALGORITHM_ID_EEA0: - // “all bits equal to 0” – UE supports no other algorithm than EEA0, - // specification does not cover the case in which EEA0 is supported with other algorithms - // just assume that EEA0 is always supported even this can not be explicity signaled by S1AP - sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; - enc_algo_found = true; - parent->rrc_log->info("Selected EEA0 as RRC encryption algorithm\n"); - break; - case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: - // “first bit” – 128-EEA1, - if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA1)) { - sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1; - enc_algo_found = true; - parent->rrc_log->info("Selected EEA1 as RRC encryption algorithm\n"); - break; - } else { - parent->rrc_log->info("Failed to selected EEA1 as RRC encryption algorithm, due to unsupported algorithm\n"); - } - break; - case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: - // “second bit” – 128-EEA2, - if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA2)) { - sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2; - enc_algo_found = true; - parent->rrc_log->info("Selected EEA2 as RRC encryption algorithm\n"); - break; - } else { - parent->rrc_log->info("Failed to selected EEA2 as RRC encryption algorithm, due to unsupported algorithm\n"); - } - break; - case srslte::CIPHERING_ALGORITHM_ID_128_EEA3: - // “third bit” – 128-EEA3, - if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA3)) { - sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA3; - enc_algo_found = true; - parent->rrc_log->info("Selected EEA3 as RRC encryption algorithm\n"); - break; - } else { - parent->rrc_log->info("Failed to selected EEA2 as RRC encryption algorithm, due to unsupported algorithm\n"); - } - break; - default: - enc_algo_found = false; - break; - } - if (enc_algo_found) { - break; - } - } - - for (auto& eia_enum : parent->cfg.eia_preference_list) { - auto& v = security_capabilities.integrity_protection_algorithms; - switch (eia_enum) { - case srslte::INTEGRITY_ALGORITHM_ID_EIA0: - // Null integrity is not supported - parent->rrc_log->info("Skipping EIA0 as RRC integrity algorithm. Null integrity is not supported.\n"); - break; - case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: - // “first bit” – 128-EIA1, - if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA1)) { - sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; - integ_algo_found = true; - parent->rrc_log->info("Selected EIA1 as RRC integrity algorithm.\n"); - } else { - parent->rrc_log->info("Failed to selected EIA1 as RRC encryption algorithm, due to unsupported algorithm\n"); - } - break; - case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: - // “second bit” – 128-EIA2, - if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA2)) { - sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2; - integ_algo_found = true; - parent->rrc_log->info("Selected EIA2 as RRC integrity algorithm.\n"); - } else { - parent->rrc_log->info("Failed to selected EIA2 as RRC encryption algorithm, due to unsupported algorithm\n"); - } - break; - case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: - // “third bit” – 128-EIA3, - if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA3)) { - sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA3; - integ_algo_found = true; - parent->rrc_log->info("Selected EIA3 as RRC integrity algorithm.\n"); - } else { - parent->rrc_log->info("Failed to selected EIA3 as RRC encryption algorithm, due to unsupported algorithm\n"); - } - break; - default: - integ_algo_found = false; - break; - } - - if (integ_algo_found) { - break; - } - } - - if (not integ_algo_found || not enc_algo_found) { - // TODO: if no security algorithm found abort radio connection and issue - // encryption-and-or-integrity-protection-algorithms-not-supported message - parent->rrc_log->error("Did not find a matching integrity or encryption algorithm with the UE\n"); - return false; - } - return true; -} void rrc::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) { // Allocate a new PDU buffer, pack the message and send to PDCP diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index beeb47f9a..768920eae 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -62,7 +62,7 @@ uint16_t compute_mac_i(uint16_t crnti, uint32_t cellid, uint16_t pci, srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo, - uint8_t* k_rrc_int) + const uint8_t* k_rrc_int) { // Compute shortMAC-I uint8_t varShortMAC_packed[16] = {}; @@ -890,7 +890,7 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, // hoprep_r8.as_cfg.source_rr_cfg.drb_to_release_list_present = true; // hoprep_r8.as_cfg.source_rr_cfg.drb_to_release_list.resize(1); // hoprep_r8.as_cfg.source_rr_cfg.drb_to_release_list[0] = 1; - hoprep_r8.as_cfg.source_security_algorithm_cfg = rrc_ue->last_security_mode_cmd; + hoprep_r8.as_cfg.source_security_algorithm_cfg = rrc_ue->ue_security_cfg.get_security_algorithm_cfg(); hoprep_r8.as_cfg.source_ue_id.from_number(rrc_ue->rnti); asn1::number_to_enum(hoprep_r8.as_cfg.source_mib.dl_bw, rrc_enb->cfg.cell.nof_prb); hoprep_r8.as_cfg.source_mib.phich_cfg.phich_dur.value = @@ -911,8 +911,8 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, rrc_details::compute_mac_i(rrc_ue->rnti, rrc_enb->cfg.sib1.cell_access_related_info.cell_id.to_number(), rrc_enb->cfg.cell_list.at(0).pci, // TODO: use actual PCI of source cell - rrc_ue->sec_cfg.integ_algo, - rrc_ue->sec_cfg.k_rrc_int.data())); + rrc_ue->ue_security_cfg.get_as_sec_cfg().integ_algo, + rrc_ue->ue_security_cfg.get_as_sec_cfg().k_rrc_int.data())); /*** pack HO Preparation Info into an RRC container buffer ***/ srslte::unique_byte_buffer_t buffer = srslte::allocate_unique_buffer(*pool); diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index cd7bfc498..a611c2019 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -20,6 +20,7 @@ */ #include "srsenb/hdr/stack/rrc/rrc_ue.h" +#include "srsenb/hdr/stack/upper/common_enb.h" #include "srslte/asn1/rrc_asn1_utils.h" #include "srslte/interfaces/sched_interface.h" #include "srslte/rrc/bearer_cfg.h" @@ -28,25 +29,175 @@ namespace srsenb { using namespace asn1::rrc; -bearer_handler::bearer_handler(uint16_t rnti_, - const rrc_cfg_t& cfg_, - pdcp_interface_rrc* pdcp_, - rlc_interface_rrc* rlc_, - mac_interface_rrc* mac_, - gtpu_interface_rrc* gtpu_, - sched_interface::ue_cfg_t& ue_cfg_) : - rnti(rnti_), - cfg(&cfg_), - pdcp(pdcp_), - rlc(rlc_), - mac(mac_), - gtpu(gtpu_), - sched_ue_cfg(&ue_cfg_) +asn1::rrc::security_algorithm_cfg_s security_cfg_handler::get_security_algorithm_cfg() +{ + asn1::rrc::security_algorithm_cfg_s ret; + // TODO: select these based on UE capabilities and preference order + ret.integrity_prot_algorithm = (security_algorithm_cfg_s::integrity_prot_algorithm_e_::options)sec_cfg.integ_algo; + ret.ciphering_algorithm = (ciphering_algorithm_r12_e::options)sec_cfg.cipher_algo; + return ret; +} + +bool security_cfg_handler::set_security_capabilities(const asn1::s1ap::ue_security_cap_s& caps) +{ + security_capabilities = caps; + + // Selects security algorithms (cipher_algo and integ_algo) based on capabilities and config preferences + // Each position in the bitmap represents an encryption algorithm: + // “all bits equal to 0” – UE supports no other algorithm than EEA0, + // “first bit” – 128-EEA1, + // “second bit” – 128-EEA2, + // “third bit” – 128-EEA3, + // other bits reserved for future use. Value ‘1’ indicates support and value + // ‘0’ indicates no support of the algorithm. + // Algorithms are defined in TS 33.401 [15]. + // Note: information missing + + bool enc_algo_found = false; + bool integ_algo_found = false; + + for (auto& cipher_item : cfg->eea_preference_list) { + auto& v = security_capabilities.encryption_algorithms; + switch (cipher_item) { + case srslte::CIPHERING_ALGORITHM_ID_EEA0: + // “all bits equal to 0” – UE supports no other algorithm than EEA0, + // specification does not cover the case in which EEA0 is supported with other algorithms + // just assume that EEA0 is always supported even this can not be explicity signaled by S1AP + sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0; + enc_algo_found = true; + log_h->info("Selected EEA0 as RRC encryption algorithm\n"); + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA1: + // “first bit” – 128-EEA1, + if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA1)) { + sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1; + enc_algo_found = true; + log_h->info("Selected EEA1 as RRC encryption algorithm\n"); + break; + } else { + log_h->info("Failed to selected EEA1 as RRC encryption algorithm, due to unsupported algorithm\n"); + } + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA2: + // “second bit” – 128-EEA2, + if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA2)) { + sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2; + enc_algo_found = true; + log_h->info("Selected EEA2 as RRC encryption algorithm\n"); + break; + } else { + log_h->info("Failed to selected EEA2 as RRC encryption algorithm, due to unsupported algorithm\n"); + } + break; + case srslte::CIPHERING_ALGORITHM_ID_128_EEA3: + // “third bit” – 128-EEA3, + if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA3)) { + sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA3; + enc_algo_found = true; + log_h->info("Selected EEA3 as RRC encryption algorithm\n"); + break; + } else { + log_h->info("Failed to selected EEA2 as RRC encryption algorithm, due to unsupported algorithm\n"); + } + break; + default: + enc_algo_found = false; + break; + } + if (enc_algo_found) { + break; + } + } + + for (auto& eia_enum : cfg->eia_preference_list) { + auto& v = security_capabilities.integrity_protection_algorithms; + switch (eia_enum) { + case srslte::INTEGRITY_ALGORITHM_ID_EIA0: + // Null integrity is not supported + log_h->info("Skipping EIA0 as RRC integrity algorithm. Null integrity is not supported.\n"); + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1: + // “first bit” – 128-EIA1, + if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA1)) { + sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1; + integ_algo_found = true; + log_h->info("Selected EIA1 as RRC integrity algorithm.\n"); + } else { + log_h->info("Failed to selected EIA1 as RRC encryption algorithm, due to unsupported algorithm\n"); + } + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2: + // “second bit” – 128-EIA2, + if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA2)) { + sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2; + integ_algo_found = true; + log_h->info("Selected EIA2 as RRC integrity algorithm.\n"); + } else { + log_h->info("Failed to selected EIA2 as RRC encryption algorithm, due to unsupported algorithm\n"); + } + break; + case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3: + // “third bit” – 128-EIA3, + if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA3)) { + sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA3; + integ_algo_found = true; + log_h->info("Selected EIA3 as RRC integrity algorithm.\n"); + } else { + log_h->info("Failed to selected EIA3 as RRC encryption algorithm, due to unsupported algorithm\n"); + } + break; + default: + integ_algo_found = false; + break; + } + + if (integ_algo_found) { + break; + } + } + + if (not integ_algo_found || not enc_algo_found) { + // TODO: if no security algorithm found abort radio connection and issue + // encryption-and-or-integrity-protection-algorithms-not-supported message + log_h->error("Did not find a matching integrity or encryption algorithm with the UE\n"); + return false; + } + return true; +} + +void security_cfg_handler::set_security_key(const asn1::fixed_bitstring<256, false, true>& key) { - pool = srslte::byte_buffer_pool::get_instance(); + for (uint32_t i = 0; i < key.nof_octets(); ++i) { + k_enb[i] = key.data()[key.nof_octets() - 1 - i]; + } + log_h->info_hex(k_enb, 32, "Key eNodeB (k_enb)"); + + log_h->info("Selected security algorithms EEA: EEA%d EIA: EIA%d\n", sec_cfg.cipher_algo, sec_cfg.integ_algo); + + // Generate K_rrc_enc and K_rrc_int + srslte::security_generate_k_rrc( + k_enb, 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_up( + k_enb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_up_enc.data(), sec_cfg.k_up_int.data()); + + log_h->info_hex(sec_cfg.k_rrc_enc.data(), 32, "RRC Encryption Key (k_rrc_enc)"); + log_h->info_hex(sec_cfg.k_rrc_int.data(), 32, "RRC Integrity Key (k_rrc_int)"); + log_h->info_hex(sec_cfg.k_up_enc.data(), 32, "UP Encryption Key (k_up_enc)"); } -void bearer_handler::setup_srb(uint8_t srb_id) +/***************************** + * Bearer Handler + ****************************/ + +bearer_handler::bearer_handler(uint16_t rnti_, const rrc_cfg_t& cfg_, gtpu_interface_rrc* gtpu_) : + rnti(rnti_), + cfg(&cfg_), + gtpu(gtpu_) +{} + +void bearer_handler::add_srb(uint8_t srb_id) { if (srb_id > 2 or srb_id == 0) { log_h->error("Invalid SRB id=%d\n", srb_id); @@ -61,11 +212,11 @@ void bearer_handler::setup_srb(uint8_t srb_id) srb_it->rlc_cfg.set(srb_to_add_mod_s::rlc_cfg_c_::types_opts::default_value); } -int bearer_handler::setup_erab(uint8_t erab_id, - const asn1::s1ap::erab_level_qos_params_s& qos, - const asn1::bounded_bitstring<1, 160, true, true>& addr, - uint32_t teid_out, - const asn1::unbounded_octstring* nas_pdu) +int bearer_handler::add_erab(uint8_t erab_id, + const asn1::s1ap::erab_level_qos_params_s& qos, + const asn1::bounded_bitstring<1, 160, true, true>& addr, + uint32_t teid_out, + const asn1::unbounded_octstring* nas_pdu) { if (erab_id < 5) { log_h->error("ERAB id=%d is invalid\n", erab_id); @@ -144,29 +295,32 @@ void bearer_handler::release_erabs() } } -void bearer_handler::handle_rrc_setup(asn1::rrc::rrc_conn_setup_r8_ies_s* msg) +void bearer_handler::rr_ded_cfg_complete() { - fill_and_apply_bearer_updates(msg->rr_cfg_ded); -} + // Apply changes in internal bearer_handler DRB/SRBtoAddModLists + srslte::apply_addmodlist_diff(last_srbs, srbs_to_add, last_srbs); + srslte::apply_addmodremlist_diff(last_drbs, drbs_to_add, drbs_to_release, last_drbs); -void bearer_handler::handle_rrc_reest(asn1::rrc::rrc_conn_reest_r8_ies_s* msg) -{ - fill_and_apply_bearer_updates(msg->rr_cfg_ded); + // Reset DRBs/SRBs to Add/mod/release + srbs_to_add = {}; + drbs_to_add = {}; + drbs_to_release.resize(0); } -void bearer_handler::handle_rrc_reconf(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg) +bool bearer_handler::fill_rr_cfg_ded(asn1::rrc::rr_cfg_ded_s& msg) { - fill_and_apply_bearer_updates(msg->rr_cfg_ded); - msg->rr_cfg_ded_present = msg->rr_cfg_ded.drb_to_add_mod_list_present or - msg->rr_cfg_ded.srb_to_add_mod_list_present or msg->rr_cfg_ded.drb_to_release_list_present; - - // Config RLC/PDCP - fill_pending_nas_info(msg); + // Add altered bearers to message + msg.srb_to_add_mod_list_present = srbs_to_add.size() > 0; + msg.srb_to_add_mod_list = srbs_to_add; + msg.drb_to_add_mod_list_present = drbs_to_add.size() > 0; + msg.drb_to_add_mod_list = drbs_to_add; + msg.drb_to_release_list_present = drbs_to_release.size() > 0; + msg.drb_to_release_list = drbs_to_release; + return msg.srb_to_add_mod_list_present or msg.drb_to_add_mod_list_present or msg.drb_to_release_list_present; } -void bearer_handler::handle_rrc_reconf_complete() +void bearer_handler::apply_mac_bearer_updates(mac_interface_rrc* mac, sched_interface::ue_cfg_t* sched_ue_cfg) { - // Finally, add SRB2 and DRBs and any dedicated DRBs to the scheduler srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg = {}; for (const srb_to_add_mod_s& srb : srbs_to_add) { bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH; @@ -185,59 +339,54 @@ void bearer_handler::handle_rrc_reconf_complete() mac->bearer_ue_cfg(rnti, drb.lc_ch_id, &bearer_cfg); sched_ue_cfg->ue_bearers[drb.lc_ch_id] = bearer_cfg; } - - // Acknowledge Dedicated Configuration - mac->phy_config_enabled(rnti, true); - - // Reset ToAdd state - srbs_to_add = {}; - drbs_to_add = {}; - drbs_to_release.resize(0); } -void bearer_handler::fill_and_apply_bearer_updates(asn1::rrc::rr_cfg_ded_s& msg) +void bearer_handler::apply_pdcp_bearer_updates(pdcp_interface_rrc* pdcp, const security_cfg_handler& ue_sec_cfg) { - // Add altered bearers to message - msg.srb_to_add_mod_list_present = srbs_to_add.size() > 0; - msg.srb_to_add_mod_list = srbs_to_add; - msg.drb_to_add_mod_list_present = drbs_to_add.size() > 0; - msg.drb_to_add_mod_list = drbs_to_add; - msg.drb_to_release_list_present = drbs_to_release.size() > 0; - msg.drb_to_release_list = drbs_to_release; + for (const srb_to_add_mod_s& srb : srbs_to_add) { + pdcp->add_bearer(rnti, srb.srb_id, srslte::make_srb_pdcp_config_t(srb.srb_id, false)); - // Apply changes in internal bearer_handler DRB/SRBtoAddModLists - srslte::apply_srb_diff(last_srbs, msg, last_srbs); - srslte::apply_drb_diff(last_drbs, msg, last_drbs); + // For SRB2, enable security/encryption/integrity + if (srb.srb_id > 1) { + pdcp->config_security(rnti, srb.srb_id, ue_sec_cfg.get_as_sec_cfg()); + pdcp->enable_integrity(rnti, srb.srb_id); + pdcp->enable_encryption(rnti, srb.srb_id); + } + } - // Apply SRB updates to PDCP and RLC - if (msg.srb_to_add_mod_list_present) { - for (const srb_to_add_mod_s& srb : msg.srb_to_add_mod_list) { - // Configure SRB1 in RLC - rlc->add_bearer(rnti, srb.srb_id, srslte::rlc_config_t::srb_config(srb.srb_id)); + if (drbs_to_release.size() > 0) { + log_h->warning("Removing DRBs not currently supported\n"); + } - // Configure SRB1 in PDCP - pdcp->add_bearer(rnti, srb.srb_id, srslte::make_srb_pdcp_config_t(srb.srb_id, false)); + for (const drb_to_add_mod_s& drb : drbs_to_add) { + // Configure DRB1 in PDCP + if (drb.pdcp_cfg_present) { + srslte::pdcp_config_t pdcp_cnfg_drb = srslte::make_drb_pdcp_config_t(drb.drb_id, false, drb.pdcp_cfg); + pdcp->add_bearer(rnti, drb.lc_ch_id, pdcp_cnfg_drb); + } else { + srslte::pdcp_config_t pdcp_cnfg_drb = srslte::make_drb_pdcp_config_t(drb.drb_id, false); + pdcp->add_bearer(rnti, drb.lc_ch_id, pdcp_cnfg_drb); } + + pdcp->config_security(rnti, drb.lc_ch_id, ue_sec_cfg.get_as_sec_cfg()); + pdcp->enable_integrity(rnti, drb.lc_ch_id); + pdcp->enable_encryption(rnti, drb.lc_ch_id); } +} - // Apply DRB updates to PDCP and RLC - if (msg.drb_to_release_list_present) { +void bearer_handler::apply_rlc_bearer_updates(rlc_interface_rrc* rlc) +{ + for (const srb_to_add_mod_s& srb : srbs_to_add) { + rlc->add_bearer(rnti, srb.srb_id, srslte::rlc_config_t::srb_config(srb.srb_id)); + } + if (drbs_to_release.size() > 0) { log_h->error("Removing DRBs not currently supported\n"); } - if (msg.drb_to_add_mod_list_present) { - for (const drb_to_add_mod_s& drb : msg.drb_to_add_mod_list) { - // Configure DRBs in RLC - rlc->add_bearer(rnti, drb.lc_ch_id, srslte::make_rlc_config_t(drb.rlc_cfg)); - - // Configure DRB1 in PDCP - if (drb.pdcp_cfg_present) { - srslte::pdcp_config_t pdcp_cnfg_drb = srslte::make_drb_pdcp_config_t(drb.drb_id, false, drb.pdcp_cfg); - pdcp->add_bearer(rnti, drb.lc_ch_id, pdcp_cnfg_drb); - } else { - srslte::pdcp_config_t pdcp_cnfg_drb = srslte::make_drb_pdcp_config_t(drb.drb_id, false); - pdcp->add_bearer(rnti, drb.lc_ch_id, pdcp_cnfg_drb); - } + for (const drb_to_add_mod_s& drb : drbs_to_add) { + if (not drb.rlc_cfg_present) { + log_h->warning("Default RLC DRB config not supported\n"); } + rlc->add_bearer(rnti, drb.lc_ch_id, srslte::make_rlc_config_t(drb.rlc_cfg)); } }