created security cfg handling class for rrc ue and refactor bearer_list handling

master
Francisco Paisana 5 years ago committed by Francisco Paisana
parent e605a6f367
commit d43448e8a1

@ -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,

@ -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,

@ -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;
}

@ -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 <typename AddModList>
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<AddModList>{};
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 <typename AddModList>
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<AddModList>{};
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 <typename List, typename RemFunctor, typename AddFunctor, typename ModFunctor>
void apply_cfg_list_updates(List& src_list,

@ -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];

@ -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<uint8_t*>(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);
}

@ -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<uint32_t, asn1::rrc::srb_to_add_mod_s> srbs;
std::map<uint32_t, asn1::rrc::drb_to_add_mod_s> 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;

@ -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<true>* 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<true>* 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<uint8_t, erab_t>& 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<uint8_t, std::vector<uint8_t> > erab_info_list;
std::map<uint8_t, erab_t> erabs;

@ -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, &current_sched_ue_cfg);
bearer_list.handle_rrc_reconf_complete();
bearer_list.apply_mac_bearer_updates(parent->mac, &current_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<true>* 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, &current_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, &current_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, &current_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

@ -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);

@ -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<true>* 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<true>* 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));
}
}

Loading…
Cancel
Save