gNB NR security context:

- changed variables to use nia/nea instead of eia/eea.
  - make rrc_nr_cfg a ref
  - Changed NR ciphering/integrity algo enums to their own enum
master
Pedro Alvarez 3 years ago
parent e294311034
commit c0d2e8c11d

@ -59,6 +59,28 @@ static const char integrity_algorithm_id_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20
"128-EIA2", "128-EIA2",
"128-EIA3"}; "128-EIA3"};
typedef enum {
CIPHERING_ALGORITHM_ID_NR_NEA0 = 0,
CIPHERING_ALGORITHM_ID_NR_128_NEA1,
CIPHERING_ALGORITHM_ID_NR_128_NEA2,
CIPHERING_ALGORITHM_ID_NR_128_NEA3,
CIPHERING_ALGORITHM_ID_NR_N_ITEMS,
} CIPHERING_ALGORITHM_ID_NR_ENUM;
static const char ciphering_algorithm_id_nr_text[CIPHERING_ALGORITHM_ID_N_ITEMS][20] = {"NEA0",
"128-NEA1",
"128-NEA2",
"128-NEA3"};
typedef enum {
INTEGRITY_ALGORITHM_ID_NR_NIA0 = 0,
INTEGRITY_ALGORITHM_ID_NR_128_NIA1,
INTEGRITY_ALGORITHM_ID_NR_128_NIA2,
INTEGRITY_ALGORITHM_ID_NR_128_NIA3,
INTEGRITY_ALGORITHM_ID_NR_N_ITEMS,
} INTEGRITY_ALGORITHM_ID_NR_ENUM;
static const char integrity_algorithm_id_nr_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"NIA0",
"128-NIA1",
"128-NIA2",
"128-NIA3"};
typedef enum { typedef enum {
SECURITY_DIRECTION_UPLINK = 0, SECURITY_DIRECTION_UPLINK = 0,
SECURITY_DIRECTION_DOWNLINK = 1, SECURITY_DIRECTION_DOWNLINK = 1,
@ -87,6 +109,15 @@ struct as_security_config_t {
CIPHERING_ALGORITHM_ID_ENUM cipher_algo; CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
}; };
struct nr_as_security_config_t {
as_key_t k_nr_rrc_int;
as_key_t k_nr_rrc_enc;
as_key_t k_nr_up_int;
as_key_t k_nr_up_enc;
INTEGRITY_ALGORITHM_ID_NR_ENUM integ_algo;
CIPHERING_ALGORITHM_ID_NR_ENUM cipher_algo;
};
template <typename... Args> template <typename... Args>
void log_error(const char* format, Args&&... args) void log_error(const char* format, Args&&... args)
{ {

@ -53,8 +53,8 @@ struct rrc_nr_cfg_t {
rrc_cell_list_nr_t cell_list; rrc_cell_list_nr_t cell_list;
bool is_standalone; bool is_standalone;
std::array<srsran::CIPHERING_ALGORITHM_ID_ENUM, srsran::CIPHERING_ALGORITHM_ID_N_ITEMS> eea_preference_list; std::array<srsran::CIPHERING_ALGORITHM_ID_NR_ENUM, srsran::CIPHERING_ALGORITHM_ID_NR_N_ITEMS> nea_preference_list;
std::array<srsran::INTEGRITY_ALGORITHM_ID_ENUM, srsran::INTEGRITY_ALGORITHM_ID_N_ITEMS> eia_preference_list; std::array<srsran::INTEGRITY_ALGORITHM_ID_NR_ENUM, srsran::INTEGRITY_ALGORITHM_ID_NR_N_ITEMS> nia_preference_list;
std::string log_name = "RRC-NR"; std::string log_name = "RRC-NR";
std::string log_level; std::string log_level;

@ -24,12 +24,11 @@ class nr_security_context
{ {
public: public:
explicit nr_security_context(const srsenb::rrc_nr_cfg_t& cfg_) : explicit nr_security_context(const srsenb::rrc_nr_cfg_t& cfg_) :
cfg(&cfg_), logger(srslog::fetch_basic_logger("RRC_NR")) cfg(cfg_), logger(srslog::fetch_basic_logger("RRC_NR"))
{} {}
explicit nr_security_context(const nr_security_context& other) : logger(srslog::fetch_basic_logger("RRC_NR")) nr_security_context(const nr_security_context& other) : cfg(other.cfg), logger(srslog::fetch_basic_logger("RRC_NR"))
{ {
cfg = other.cfg;
k_gnb_present = other.k_gnb_present; k_gnb_present = other.k_gnb_present;
security_capabilities = other.security_capabilities; security_capabilities = other.security_capabilities;
std::copy(other.k_gnb, other.k_gnb + 32, k_gnb); std::copy(other.k_gnb, other.k_gnb + 32, k_gnb);
@ -39,7 +38,6 @@ public:
nr_security_context& operator=(const nr_security_context& other) nr_security_context& operator=(const nr_security_context& other)
{ {
cfg = other.cfg;
k_gnb_present = other.k_gnb_present; k_gnb_present = other.k_gnb_present;
security_capabilities = other.security_capabilities; security_capabilities = other.security_capabilities;
std::copy(other.k_gnb, other.k_gnb + 32, k_gnb); std::copy(other.k_gnb, other.k_gnb + 32, k_gnb);
@ -53,7 +51,7 @@ public:
void set_ncc(uint8_t ncc_) { ncc = ncc_; } void set_ncc(uint8_t ncc_) { ncc = ncc_; }
asn1::rrc_nr::security_algorithm_cfg_s get_security_algorithm_cfg() const; asn1::rrc_nr::security_algorithm_cfg_s get_security_algorithm_cfg() const;
const srsran::as_security_config_t& get_as_sec_cfg() const { return sec_cfg; } const srsran::nr_as_security_config_t& get_as_sec_cfg() const { return sec_cfg; }
uint8_t get_ncc() const { return ncc; } uint8_t get_ncc() const { return ncc; }
bool is_as_sec_cfg_valid() const { return k_gnb_present; } bool is_as_sec_cfg_valid() const { return k_gnb_present; }
@ -63,11 +61,11 @@ private:
void generate_as_keys(); void generate_as_keys();
srslog::basic_logger& logger; srslog::basic_logger& logger;
const srsenb::rrc_nr_cfg_t* cfg = nullptr; const srsenb::rrc_nr_cfg_t& cfg;
bool k_gnb_present = false; bool k_gnb_present = false;
asn1::ngap_nr::ue_security_cap_s security_capabilities = {}; asn1::ngap_nr::ue_security_cap_s security_capabilities = {};
uint8_t k_gnb[32] = {}; // Provided by MME uint8_t k_gnb[32] = {}; // Provided by MME
srsran::as_security_config_t sec_cfg = {}; srsran::nr_as_security_config_t sec_cfg = {};
uint8_t ncc = 0; uint8_t ncc = 0;
}; };
} // namespace srsgnb } // namespace srsgnb

@ -31,10 +31,10 @@ bool nr_security_context::set_security_capabilities(const asn1::ngap_nr::ue_secu
// Selects security algorithms (cipher_algo and integ_algo) based on capabilities and config preferences // Selects security algorithms (cipher_algo and integ_algo) based on capabilities and config preferences
// Each position in the bitmap represents an encryption algorithm: // Each position in the bitmap represents an encryption algorithm:
// “all bits equal to 0” UE supports no other algorithm than EEA0, // “all bits equal to 0” UE supports no other algorithm than NEA0,
// “first bit” 128-EEA1, // “first bit” 128-NEA1,
// “second bit” 128-EEA2, // “second bit” 128-NEA2,
// “third bit” 128-EEA3, // “third bit” 128-NEA3,
// other bits reserved for future use. Value 1 indicates support and value // other bits reserved for future use. Value 1 indicates support and value
// 0 indicates no support of the algorithm. // 0 indicates no support of the algorithm.
// Algorithms are defined in TS 33.401 [15]. // Algorithms are defined in TS 33.401 [15].
@ -43,48 +43,48 @@ bool nr_security_context::set_security_capabilities(const asn1::ngap_nr::ue_secu
bool enc_algo_found = false; bool enc_algo_found = false;
bool integ_algo_found = false; bool integ_algo_found = false;
for (auto& cipher_item : cfg->eea_preference_list) { for (const auto& cipher_item : cfg.nea_preference_list) {
auto& v = security_capabilities.nrencryption_algorithms; auto& v = security_capabilities.nrencryption_algorithms;
switch (cipher_item) { switch (cipher_item) {
case srsran::CIPHERING_ALGORITHM_ID_EEA0: case srsran::CIPHERING_ALGORITHM_ID_NR_NEA0:
// “all bits equal to 0” UE supports no other algorithm than 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 // 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 // just assume that EEA0 is always supported even this can not be explicity signaled by S1AP
sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_EEA0; sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_NR_NEA0;
enc_algo_found = true; enc_algo_found = true;
logger.info("Selected EEA0 as RRC encryption algorithm"); logger.info("Selected NEA0 as RRC encryption algorithm");
break; break;
case srsran::CIPHERING_ALGORITHM_ID_128_EEA1: case srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA1:
// “first bit” 128-EEA1, // “first bit” 128-EEA1,
if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_128_EEA1)) { if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA1)) {
sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_128_EEA1; sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA1;
enc_algo_found = true; enc_algo_found = true;
logger.info("Selected EEA1 as RRC encryption algorithm"); logger.info("Selected NEA1 as RRC encryption algorithm");
break; break;
} else { } else {
logger.info("Failed to selected EEA1 as RRC encryption algorithm, due to unsupported algorithm"); logger.info("Failed to selected NEA1 as RRC encryption algorithm, due to unsupported algorithm");
} }
break; break;
case srsran::CIPHERING_ALGORITHM_ID_128_EEA2: case srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA2:
// “second bit” 128-EEA2, // “second bit” 128-EEA2,
if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_128_EEA2)) { if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA2)) {
sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_128_EEA2; sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA2;
enc_algo_found = true; enc_algo_found = true;
logger.info("Selected EEA2 as RRC encryption algorithm"); logger.info("Selected NEA2 as RRC encryption algorithm");
break; break;
} else { } else {
logger.info("Failed to selected EEA2 as RRC encryption algorithm, due to unsupported algorithm"); logger.info("Failed to selected NEA2 as RRC encryption algorithm, due to unsupported algorithm");
} }
break; break;
case srsran::CIPHERING_ALGORITHM_ID_128_EEA3: case srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA3:
// “third bit” 128-EEA3, // “third bit” 128-EEA3,
if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_128_EEA3)) { if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA3)) {
sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_128_EEA3; sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA3;
enc_algo_found = true; enc_algo_found = true;
logger.info("Selected EEA3 as RRC encryption algorithm"); logger.info("Selected NEA3 as RRC encryption algorithm");
break; break;
} else { } else {
logger.info("Failed to selected EEA2 as RRC encryption algorithm, due to unsupported algorithm"); logger.info("Failed to selected NEA2 as RRC encryption algorithm, due to unsupported algorithm");
} }
break; break;
default: default:
@ -96,43 +96,43 @@ bool nr_security_context::set_security_capabilities(const asn1::ngap_nr::ue_secu
} }
} }
for (auto& eia_enum : cfg->eia_preference_list) { for (const auto& eia_enum : cfg.nia_preference_list) {
auto& v = security_capabilities.nrintegrity_protection_algorithms; auto& v = security_capabilities.nrintegrity_protection_algorithms;
switch (eia_enum) { switch (eia_enum) {
case srsran::INTEGRITY_ALGORITHM_ID_EIA0: case srsran::INTEGRITY_ALGORITHM_ID_NR_NIA0:
// Null integrity is not supported // Null integrity is not supported
logger.info("Skipping EIA0 as RRC integrity algorithm. Null integrity is not supported."); logger.info("Skipping NIA0 as RRC integrity algorithm. Null integrity is not supported.");
sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_EIA0; sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_NR_NIA0;
integ_algo_found = true; integ_algo_found = true;
break; break;
case srsran::INTEGRITY_ALGORITHM_ID_128_EIA1: case srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA1:
// “first bit” 128-EIA1, // “first bit” 128-EIA1,
if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_128_EIA1)) { if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA1)) {
sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_128_EIA1; sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA1;
integ_algo_found = true; integ_algo_found = true;
logger.info("Selected EIA1 as RRC integrity algorithm."); logger.info("Selected NIA1 as RRC integrity algorithm.");
} else { } else {
logger.info("Failed to selected EIA1 as RRC encryption algorithm, due to unsupported algorithm"); logger.info("Failed to selected NIA1 as RRC encryption algorithm, due to unsupported algorithm");
} }
break; break;
case srsran::INTEGRITY_ALGORITHM_ID_128_EIA2: case srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA2:
// “second bit” 128-EIA2, // “second bit” 128-EIA2,
if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_128_EIA2)) { if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA2)) {
sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_128_EIA2; sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA2;
integ_algo_found = true; integ_algo_found = true;
logger.info("Selected EIA2 as RRC integrity algorithm."); logger.info("Selected NIA2 as RRC integrity algorithm.");
} else { } else {
logger.info("Failed to selected EIA2 as RRC encryption algorithm, due to unsupported algorithm"); logger.info("Failed to selected NIA2 as RRC encryption algorithm, due to unsupported algorithm");
} }
break; break;
case srsran::INTEGRITY_ALGORITHM_ID_128_EIA3: case srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA3:
// “third bit” 128-EIA3, // “third bit” 128-EIA3,
if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_128_EIA3)) { if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA3)) {
sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_128_EIA3; sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA3;
integ_algo_found = true; integ_algo_found = true;
logger.info("Selected EIA3 as RRC integrity algorithm."); logger.info("Selected NIA3 as RRC integrity algorithm.");
} else { } else {
logger.info("Failed to selected EIA3 as RRC encryption algorithm, due to unsupported algorithm"); logger.info("Failed to selected NIA3 as RRC encryption algorithm, due to unsupported algorithm");
} }
break; break;
default: default:
@ -166,24 +166,30 @@ void nr_security_context::set_security_key(const asn1::fixed_bitstring<256, fals
void nr_security_context::generate_as_keys() void nr_security_context::generate_as_keys()
{ {
// Generate K_rrc_enc and K_rrc_int // Generate K_rrc_enc and K_rrc_int
srsran::security_generate_k_nr_rrc( srsran::security_generate_k_nr_rrc(k_gnb,
k_gnb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_rrc_enc.data(), sec_cfg.k_rrc_int.data()); (srsran::CIPHERING_ALGORITHM_ID_ENUM)sec_cfg.cipher_algo,
(srsran::INTEGRITY_ALGORITHM_ID_ENUM)sec_cfg.integ_algo,
sec_cfg.k_nr_rrc_enc.data(),
sec_cfg.k_nr_rrc_int.data());
// Generate K_up_enc and K_up_int // Generate K_up_enc and K_up_int
security_generate_k_nr_up( security_generate_k_nr_up(k_gnb,
k_gnb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_up_enc.data(), sec_cfg.k_up_int.data()); (srsran::CIPHERING_ALGORITHM_ID_ENUM)sec_cfg.cipher_algo,
(srsran::INTEGRITY_ALGORITHM_ID_ENUM)sec_cfg.integ_algo,
sec_cfg.k_nr_up_enc.data(),
sec_cfg.k_nr_up_int.data());
logger.info(k_gnb, 32, "K_gNB (k_gnb)"); logger.info(k_gnb, 32, "K_gNB (k_gnb)");
logger.info(sec_cfg.k_rrc_enc.data(), 32, "RRC Encryption Key (k_rrc_enc)"); logger.info(sec_cfg.k_nr_rrc_enc.data(), 32, "NR RRC Encryption Key (k_nr_rrc_enc)");
logger.info(sec_cfg.k_rrc_int.data(), 32, "RRC Integrity Key (k_rrc_int)"); logger.info(sec_cfg.k_nr_rrc_int.data(), 32, "NR RRC Integrity Key (k_nr_rrc_int)");
logger.info(sec_cfg.k_up_enc.data(), 32, "UP Encryption Key (k_up_enc)"); logger.info(sec_cfg.k_nr_up_enc.data(), 32, "NR UP Encryption Key (k_nr_up_enc)");
logger.info(sec_cfg.k_up_int.data(), 32, "UP Encryption Key (k_up_enc)"); logger.info(sec_cfg.k_nr_up_int.data(), 32, "NR UP Encryption Key (k_nr_up_enc)");
} }
void nr_security_context::regenerate_keys_handover(uint32_t new_pci, uint32_t new_dl_earfcn) void nr_security_context::regenerate_keys_handover(uint32_t new_pci, uint32_t new_dl_earfcn)
{ {
logger.info("Regenerating KeNB with PCI=0x%02x, DL-EARFCN=%d", new_pci, new_dl_earfcn); logger.info("Regenerating KgNB with PCI=0x%02x, DL-EARFCN=%d", new_pci, new_dl_earfcn);
logger.info(k_gnb, 32, "Old K_eNB (k_enb)"); logger.info(k_gnb, 32, "Old K_gNB (k_enb)");
// Generate K_enb* // Generate K_enb*
uint8_t k_gnb_star[32]; uint8_t k_gnb_star[32];
srsran::security_generate_k_enb_star(k_gnb, new_pci, new_dl_earfcn, k_gnb_star); srsran::security_generate_k_enb_star(k_gnb, new_pci, new_dl_earfcn, k_gnb_star);

Loading…
Cancel
Save