ttcn3_ss: fix security activation for PDCP

master
Andre Puschmann 5 years ago
parent 9e113f8b27
commit e7c10270fa

@ -48,9 +48,11 @@ public:
} timing_info_t; } timing_info_t;
typedef struct { typedef struct {
bool rb_is_srb;
uint8_t rb_id; uint8_t rb_id;
bool rb_is_srb;
bool ul_value_valid;
uint16_t ul_value; uint16_t ul_value;
bool dl_value_valid;
uint16_t dl_value; uint16_t dl_value;
} pdcp_count_t; } pdcp_count_t;
typedef std::vector<ttcn3_helpers::pdcp_count_t> pdcp_count_map_t; typedef std::vector<ttcn3_helpers::pdcp_count_t> pdcp_count_map_t;

@ -44,37 +44,44 @@ class ss_sys_interface
public: public:
virtual void add_bcch_dlsch_pdu(const std::string cell_name, srslte::unique_byte_buffer_t pdu) = 0; virtual void add_bcch_dlsch_pdu(const std::string cell_name, srslte::unique_byte_buffer_t pdu) = 0;
virtual void add_pch_pdu(srslte::unique_byte_buffer_t pdu) = 0; virtual void add_pch_pdu(srslte::unique_byte_buffer_t pdu) = 0;
virtual void set_cell_attenuation(const ttcn3_helpers::timing_info_t timing, virtual void set_cell_attenuation(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name, const std::string cell_name,
const float attenuation) = 0; const float attenuation) = 0;
virtual void set_cell_config(const ttcn3_helpers::timing_info_t timing, virtual void set_cell_config(const ttcn3_helpers::timing_info_t timing,
const std::string cell_name, const std::string cell_name,
const uint32_t earfcn, const uint32_t earfcn,
const srslte_cell_t cell, const srslte_cell_t cell,
const float power) = 0; const float power) = 0;
virtual void virtual void
add_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid, const srslte::pdcp_config_t pdcp_config) = 0; add_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid, const srslte::pdcp_config_t pdcp_config) = 0;
virtual void del_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid) = 0; virtual void del_srb(const ttcn3_helpers::timing_info_t timing, const uint32_t lcid) = 0;
virtual uint32_t get_tti() = 0;
virtual void set_as_security(const ttcn3_helpers::timing_info_t timing, virtual void set_as_security(const ttcn3_helpers::timing_info_t timing,
const uint32_t lcid,
const std::array<uint8_t, 32> k_rrc_enc, const std::array<uint8_t, 32> k_rrc_enc,
const std::array<uint8_t, 32> k_rrc_int, const std::array<uint8_t, 32> k_rrc_int,
const std::array<uint8_t, 32> k_up_enc, const std::array<uint8_t, 32> k_up_enc,
const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0; const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo,
const ttcn3_helpers::pdcp_count_map_t bearers) = 0;
virtual void release_as_security(const ttcn3_helpers::timing_info_t timing) = 0; virtual void release_as_security(const ttcn3_helpers::timing_info_t timing) = 0;
virtual ttcn3_helpers::pdcp_count_map_t get_pdcp_count() = 0;
virtual ttcn3_helpers::pdcp_count_map_t get_pdcp_count() = 0;
virtual uint32_t get_tti() = 0;
}; };
class ss_srb_interface class ss_srb_interface
{ {
public: public:
virtual void add_ccch_pdu(const ttcn3_helpers::timing_info_t timing, srslte::unique_byte_buffer_t pdu) = 0; virtual void add_ccch_pdu(const ttcn3_helpers::timing_info_t timing, srslte::unique_byte_buffer_t pdu) = 0;
virtual void add_dcch_pdu(const ttcn3_helpers::timing_info_t timing, virtual void add_dcch_pdu(const ttcn3_helpers::timing_info_t timing,
uint32_t lcid, uint32_t lcid,
srslte::unique_byte_buffer_t pdu, srslte::unique_byte_buffer_t pdu,
bool follow_on_flag) = 0; bool follow_on_flag) = 0;
virtual void reestablish_bearer(uint32_t lcid) = 0; virtual void reestablish_bearer(uint32_t lcid) = 0;
}; };

@ -456,22 +456,44 @@ private:
std::array<uint8_t, 32> k_up_enc = get_key_from_string(up_enc_key_string); std::array<uint8_t, 32> k_up_enc = get_key_from_string(up_enc_key_string);
log->debug_hex(k_up_enc.data(), k_up_enc.size(), "K_UP_enc"); log->debug_hex(k_up_enc.data(), k_up_enc.size(), "K_UP_enc");
// get LCID // parse ActTimeList
uint32_t lcid = 0; ttcn3_helpers::pdcp_count_map_t bearers;
if (as_sec["StartRestart"]["Ciphering"].HasMember("ActTimeList")) { if (as_sec["StartRestart"]["Ciphering"].HasMember("ActTimeList")) {
const Value& act_time_list = as_sec["StartRestart"]["Ciphering"]["ActTimeList"]; const Value& act_time_list = as_sec["StartRestart"]["Ciphering"]["ActTimeList"];
if (act_time_list.IsArray()) { if (act_time_list.IsArray()) {
for (Value::ConstValueIterator itr = act_time_list.Begin(); itr != act_time_list.End(); ++itr) { for (Value::ConstValueIterator itr = act_time_list.Begin(); itr != act_time_list.End(); ++itr) {
ttcn3_helpers::pdcp_count_t bearer = {};
// obtain LCID and type
if (itr->HasMember("RadioBearerId") && (*itr)["RadioBearerId"].HasMember("Srb")) { if (itr->HasMember("RadioBearerId") && (*itr)["RadioBearerId"].HasMember("Srb")) {
lcid = (*itr)["RadioBearerId"]["Srb"].GetInt(); bearer.rb_is_srb = true;
bearer.rb_id = (*itr)["RadioBearerId"]["Srb"].GetInt();
} else if (itr->HasMember("RadioBearerId") && (*itr)["RadioBearerId"].HasMember("Drb")) {
bearer.rb_is_srb = false;
bearer.rb_id = (*itr)["RadioBearerId"]["Drb"].GetInt();
}
// obtain UL count
if (itr->HasMember("UL")) {
bearer.ul_value = (*itr)["UL"]["SQN"]["Value"].GetInt();
bearer.ul_value_valid = true;
} }
// obtain DL count
if (itr->HasMember("DL")) {
bearer.dl_value = (*itr)["DL"]["SQN"]["Value"].GetInt();
bearer.dl_value_valid = true;
}
// append to list
bearers.push_back(bearer);
} }
} }
} }
// configure SS to use AS security // configure SS to use AS security
syssim->set_as_security( syssim->set_as_security(
ttcn3_helpers::get_timing_info(document), lcid, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo); ttcn3_helpers::get_timing_info(document), k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo, bearers);
} else if (as_sec.HasMember("Release")) { } else if (as_sec.HasMember("Release")) {
// release all security configs // release all security configs
syssim->release_as_security(ttcn3_helpers::get_timing_info(document)); syssim->release_as_security(ttcn3_helpers::get_timing_info(document));

@ -209,6 +209,12 @@ public:
} }
} }
// trying to apply pending PDCP config
if (not pending_bearer_config.empty()) {
log.debug("Trying to apply pending PDCP config\n");
pending_bearer_config = try_set_pdcp_security(pending_bearer_config);
}
// process events, if any // process events, if any
while (not event_queue.empty()) { while (not event_queue.empty()) {
ss_events_t ev = event_queue.wait_pop(); ss_events_t ev = event_queue.wait_pop();
@ -364,8 +370,8 @@ public:
rlc.reset(); rlc.reset();
pdcp.reset(); pdcp.reset();
cells.clear(); cells.clear();
pcell_idx = -1; pcell_idx = -1;
as_security_enabled = false; pending_bearer_config.clear();
} }
// Called from UT before starting testcase // Called from UT before starting testcase
@ -881,14 +887,6 @@ public:
log.info("Adding SRB%d\n", lcid); log.info("Adding SRB%d\n", lcid);
pdcp.add_bearer(lcid, pdcp_config); pdcp.add_bearer(lcid, pdcp_config);
rlc.add_bearer(lcid, srslte::rlc_config_t::srb_config(lcid)); rlc.add_bearer(lcid, srslte::rlc_config_t::srb_config(lcid));
// Enable security for SRB2
if (lcid == 2) {
log.info("Enabling AS security for LCID=%d\n", lcid);
pdcp.config_security(lcid, k_rrc_enc.data(), k_rrc_int.data(), k_up_enc.data(), cipher_algo, integ_algo);
pdcp.enable_encryption(lcid);
pdcp.enable_integrity(lcid);
}
} }
void reestablish_bearer(uint32_t lcid) void reestablish_bearer(uint32_t lcid)
@ -995,50 +993,103 @@ public:
bool rb_is_um(uint32_t lcid) { return false; } bool rb_is_um(uint32_t lcid) { return false; }
void set_as_security(const ttcn3_helpers::timing_info_t timing, void set_as_security(const ttcn3_helpers::timing_info_t timing,
const uint32_t lcid,
std::array<uint8_t, 32> k_rrc_enc_, std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_int_, std::array<uint8_t, 32> k_rrc_int_,
std::array<uint8_t, 32> k_up_enc_, std::array<uint8_t, 32> k_up_enc_,
const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_,
const ttcn3_helpers::pdcp_count_map_t bearers_)
{ {
if (timing.now) { if (timing.now) {
set_as_security_impl(lcid, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_); set_as_security_impl(k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_);
} else { } else {
log.debug("Scheduling AS security configuration of lcid=%d for TTI=%d\n", lcid, timing.tti); log.debug("Scheduling AS security configuration for TTI=%d\n", timing.tti);
tti_actions[timing.tti].push_back([this, lcid, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_]() { tti_actions[timing.tti].push_back(
set_as_security_impl(lcid, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_); [this, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_]() {
}); set_as_security_impl(k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_, bearers_);
});
} }
} }
void set_as_security_impl(const uint32_t lcid, void set_as_security_impl(std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_enc_,
std::array<uint8_t, 32> k_rrc_int_, std::array<uint8_t, 32> k_rrc_int_,
std::array<uint8_t, 32> k_up_enc_, std::array<uint8_t, 32> k_up_enc_,
const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_,
const ttcn3_helpers::pdcp_count_map_t bearers)
{
// store security config for later use (i.e. new bearer added)
k_rrc_enc = k_rrc_enc_;
k_rrc_int = k_rrc_int_;
k_up_enc = k_up_enc_;
cipher_algo = cipher_algo_;
integ_algo = integ_algo_;
// try to apply security config on bearers
pending_bearer_config = try_set_pdcp_security(bearers);
}
/**
* Try to configure PDCP security on the list of provided bearers.
*
* The function iterates over the map of bearers and tries to set/update
* the security settings, if and only if, the current DL/UL counter match
* with the requested values in the bearer map.
*
* The function returns a map of bearers for which it could not update the
* configuration.
*
* @param bearers for which PDCP configuration should be updated
* @return list of bearers for which update could not be carried out (fully)
*/
ttcn3_helpers::pdcp_count_map_t try_set_pdcp_security(ttcn3_helpers::pdcp_count_map_t bearers)
{ {
log.info("Setting AS security for LCID=%d\n", lcid); ttcn3_helpers::pdcp_count_map_t update_needed_list;
pdcp.config_security(lcid, k_rrc_enc_.data(), k_rrc_int_.data(), k_up_enc_.data(), cipher_algo_, integ_algo_);
pdcp.enable_integrity(lcid); for (auto& lcid : bearers) {
pdcp.enable_encryption(lcid); uint16_t dl_sn = 0, ul_sn = 0, tmp = 0;
pdcp.get_bearer_status(lcid.rb_id, &dl_sn, &tmp, &ul_sn, &tmp);
// if SRB2 is established, also apply security config
uint32_t srb2_lcid = 2; if (lcid.dl_value_valid) {
if (pdcp.is_lcid_enabled(2)) { // make sure the current DL SN value match
log.info("Updating AS security for LCID=%d\n", srb2_lcid); if (lcid.dl_value == dl_sn) {
pdcp.config_security( log.info("Setting AS security for LCID=%d in DL direction\n", lcid.rb_id);
srb2_lcid, k_rrc_enc_.data(), k_rrc_int_.data(), k_up_enc_.data(), cipher_algo_, integ_algo_); pdcp.config_security(
lcid.rb_id, k_rrc_enc.data(), k_rrc_int.data(), k_up_enc.data(), cipher_algo, integ_algo);
pdcp.enable_integrity(lcid.rb_id, DIRECTION_TX);
pdcp.enable_encryption(lcid.rb_id, DIRECTION_TX);
lcid.dl_value_valid = false;
} else {
log.info("Delaying AS security configuration of lcid=%d. DL: %d != %d\n", lcid.rb_id, lcid.dl_value, dl_sn);
}
} else {
log.debug("Downlink AS Security already applied for lcid=%d\n", lcid.rb_id);
}
if (lcid.ul_value_valid) {
// Check UL count
if (lcid.ul_value == ul_sn) {
log.info("Setting AS security for LCID=%d in UL direction\n", lcid.rb_id);
pdcp.config_security(
lcid.rb_id, k_rrc_enc.data(), k_rrc_int.data(), k_up_enc.data(), cipher_algo, integ_algo);
pdcp.enable_integrity(lcid.rb_id, DIRECTION_RX);
pdcp.enable_encryption(lcid.rb_id, DIRECTION_RX);
lcid.ul_value_valid = false;
} else {
log.info("Delaying AS security configuration of lcid=%d. UL: %d != %d\n", lcid.rb_id, lcid.ul_value, ul_sn);
}
} else {
log.debug("Uplink AS Security already applied for lcid=%d\n", lcid.rb_id);
}
// re-consider if at least one direction needs reconfiguration
if (lcid.dl_value_valid || lcid.ul_value_valid) {
log.debug("Adding LCID=%d for later configuration (size=%zd)\n", lcid.rb_id, update_needed_list.size());
update_needed_list.push_back(lcid);
}
} }
// store security config for later use (i.e. new bearer added) return update_needed_list;
as_security_enabled = true;
k_rrc_enc = k_rrc_enc_;
k_rrc_int = k_rrc_int_;
k_up_enc = k_up_enc_;
cipher_algo = cipher_algo_;
integ_algo = integ_algo_;
} }
void release_as_security(const ttcn3_helpers::timing_info_t timing) void release_as_security(const ttcn3_helpers::timing_info_t timing)
@ -1054,7 +1105,7 @@ public:
void release_as_security_impl() void release_as_security_impl()
{ {
log.info("Releasing AS security\n"); log.info("Releasing AS security\n");
as_security_enabled = false; pending_bearer_config.clear();
} }
void select_cell(srslte_cell_t phy_cell) void select_cell(srslte_cell_t phy_cell)
@ -1080,7 +1131,7 @@ public:
pdcp.get_bearer_status(i, &bearer.dl_value, &tmp, &bearer.ul_value, &tmp); pdcp.get_bearer_status(i, &bearer.dl_value, &tmp, &bearer.ul_value, &tmp);
bearer.rb_is_srb = i <= 2; bearer.rb_is_srb = i <= 2;
bearer.rb_id = i; bearer.rb_id = i;
log.info("PDCP count lcid=%d, dl=%d, ul=%d\n", bearer.rb_id, bearer.dl_value, bearer.ul_value); log.debug("PDCP count lcid=%d, dl=%d, ul=%d\n", bearer.rb_id, bearer.dl_value, bearer.ul_value);
bearers.push_back(bearer); bearers.push_back(bearer);
} }
} }
@ -1175,7 +1226,7 @@ private:
std::map<uint32_t, bool> bearer_follow_on_map; ///< Indicates if for a given LCID the follow_on_flag is set or not std::map<uint32_t, bool> bearer_follow_on_map; ///< Indicates if for a given LCID the follow_on_flag is set or not
// security config // security config
bool as_security_enabled = false; ttcn3_helpers::pdcp_count_map_t pending_bearer_config; ///< List of bearers with pending security configuration
std::array<uint8_t, 32> k_rrc_enc; std::array<uint8_t, 32> k_rrc_enc;
std::array<uint8_t, 32> k_rrc_int; std::array<uint8_t, 32> k_rrc_int;
std::array<uint8_t, 32> k_up_enc; std::array<uint8_t, 32> k_up_enc;

Loading…
Cancel
Save