|
|
|
@ -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
|
|
|
|
|
// 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,
|
|
|
|
|
// “all bits equal to 0” – UE supports no other algorithm than NEA0,
|
|
|
|
|
// “first bit” – 128-NEA1,
|
|
|
|
|
// “second bit” – 128-NEA2,
|
|
|
|
|
// “third bit” – 128-NEA3,
|
|
|
|
|
// 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].
|
|
|
|
@ -43,48 +43,48 @@ bool nr_security_context::set_security_capabilities(const asn1::ngap_nr::ue_secu
|
|
|
|
|
bool enc_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;
|
|
|
|
|
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,
|
|
|
|
|
// 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 = srsran::CIPHERING_ALGORITHM_ID_EEA0;
|
|
|
|
|
sec_cfg.cipher_algo = srsran::CIPHERING_ALGORITHM_ID_NR_NEA0;
|
|
|
|
|
enc_algo_found = true;
|
|
|
|
|
logger.info("Selected EEA0 as RRC encryption algorithm");
|
|
|
|
|
logger.info("Selected NEA0 as RRC encryption algorithm");
|
|
|
|
|
break;
|
|
|
|
|
case srsran::CIPHERING_ALGORITHM_ID_128_EEA1:
|
|
|
|
|
case srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA1:
|
|
|
|
|
// “first bit” – 128-EEA1,
|
|
|
|
|
if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_128_EEA1)) {
|
|
|
|
|
sec_cfg.cipher_algo = 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_NR_128_NEA1;
|
|
|
|
|
enc_algo_found = true;
|
|
|
|
|
logger.info("Selected EEA1 as RRC encryption algorithm");
|
|
|
|
|
logger.info("Selected NEA1 as RRC encryption algorithm");
|
|
|
|
|
break;
|
|
|
|
|
} 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;
|
|
|
|
|
case srsran::CIPHERING_ALGORITHM_ID_128_EEA2:
|
|
|
|
|
case srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA2:
|
|
|
|
|
// “second bit” – 128-EEA2,
|
|
|
|
|
if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_128_EEA2)) {
|
|
|
|
|
sec_cfg.cipher_algo = 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_NR_128_NEA2;
|
|
|
|
|
enc_algo_found = true;
|
|
|
|
|
logger.info("Selected EEA2 as RRC encryption algorithm");
|
|
|
|
|
logger.info("Selected NEA2 as RRC encryption algorithm");
|
|
|
|
|
break;
|
|
|
|
|
} 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;
|
|
|
|
|
case srsran::CIPHERING_ALGORITHM_ID_128_EEA3:
|
|
|
|
|
case srsran::CIPHERING_ALGORITHM_ID_NR_128_NEA3:
|
|
|
|
|
// “third bit” – 128-EEA3,
|
|
|
|
|
if (v.get(v.length() - srsran::CIPHERING_ALGORITHM_ID_128_EEA3)) {
|
|
|
|
|
sec_cfg.cipher_algo = 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_NR_128_NEA3;
|
|
|
|
|
enc_algo_found = true;
|
|
|
|
|
logger.info("Selected EEA3 as RRC encryption algorithm");
|
|
|
|
|
logger.info("Selected NEA3 as RRC encryption algorithm");
|
|
|
|
|
break;
|
|
|
|
|
} 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;
|
|
|
|
|
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;
|
|
|
|
|
switch (eia_enum) {
|
|
|
|
|
case srsran::INTEGRITY_ALGORITHM_ID_EIA0:
|
|
|
|
|
case srsran::INTEGRITY_ALGORITHM_ID_NR_NIA0:
|
|
|
|
|
// Null integrity is not supported
|
|
|
|
|
logger.info("Skipping EIA0 as RRC integrity algorithm. Null integrity is not supported.");
|
|
|
|
|
sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_EIA0;
|
|
|
|
|
logger.info("Skipping NIA0 as RRC integrity algorithm. Null integrity is not supported.");
|
|
|
|
|
sec_cfg.integ_algo = srsran::INTEGRITY_ALGORITHM_ID_NR_NIA0;
|
|
|
|
|
integ_algo_found = true;
|
|
|
|
|
break;
|
|
|
|
|
case srsran::INTEGRITY_ALGORITHM_ID_128_EIA1:
|
|
|
|
|
case srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA1:
|
|
|
|
|
// “first bit” – 128-EIA1,
|
|
|
|
|
if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_128_EIA1)) {
|
|
|
|
|
sec_cfg.integ_algo = 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_NR_128_NIA1;
|
|
|
|
|
integ_algo_found = true;
|
|
|
|
|
logger.info("Selected EIA1 as RRC integrity algorithm.");
|
|
|
|
|
logger.info("Selected NIA1 as RRC integrity algorithm.");
|
|
|
|
|
} 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;
|
|
|
|
|
case srsran::INTEGRITY_ALGORITHM_ID_128_EIA2:
|
|
|
|
|
case srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA2:
|
|
|
|
|
// “second bit” – 128-EIA2,
|
|
|
|
|
if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_128_EIA2)) {
|
|
|
|
|
sec_cfg.integ_algo = 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_NR_128_NIA2;
|
|
|
|
|
integ_algo_found = true;
|
|
|
|
|
logger.info("Selected EIA2 as RRC integrity algorithm.");
|
|
|
|
|
logger.info("Selected NIA2 as RRC integrity algorithm.");
|
|
|
|
|
} 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;
|
|
|
|
|
case srsran::INTEGRITY_ALGORITHM_ID_128_EIA3:
|
|
|
|
|
case srsran::INTEGRITY_ALGORITHM_ID_NR_128_NIA3:
|
|
|
|
|
// “third bit” – 128-EIA3,
|
|
|
|
|
if (v.get(v.length() - srsran::INTEGRITY_ALGORITHM_ID_128_EIA3)) {
|
|
|
|
|
sec_cfg.integ_algo = 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_NR_128_NIA3;
|
|
|
|
|
integ_algo_found = true;
|
|
|
|
|
logger.info("Selected EIA3 as RRC integrity algorithm.");
|
|
|
|
|
logger.info("Selected NIA3 as RRC integrity algorithm.");
|
|
|
|
|
} 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;
|
|
|
|
|
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()
|
|
|
|
|
{
|
|
|
|
|
// Generate K_rrc_enc and K_rrc_int
|
|
|
|
|
srsran::security_generate_k_nr_rrc(
|
|
|
|
|
k_gnb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_rrc_enc.data(), sec_cfg.k_rrc_int.data());
|
|
|
|
|
srsran::security_generate_k_nr_rrc(k_gnb,
|
|
|
|
|
(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
|
|
|
|
|
security_generate_k_nr_up(
|
|
|
|
|
k_gnb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_up_enc.data(), sec_cfg.k_up_int.data());
|
|
|
|
|
security_generate_k_nr_up(k_gnb,
|
|
|
|
|
(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(sec_cfg.k_rrc_enc.data(), 32, "RRC Encryption Key (k_rrc_enc)");
|
|
|
|
|
logger.info(sec_cfg.k_rrc_int.data(), 32, "RRC Integrity Key (k_rrc_int)");
|
|
|
|
|
logger.info(sec_cfg.k_up_enc.data(), 32, "UP Encryption Key (k_up_enc)");
|
|
|
|
|
logger.info(sec_cfg.k_up_int.data(), 32, "UP Encryption Key (k_up_enc)");
|
|
|
|
|
logger.info(sec_cfg.k_nr_rrc_enc.data(), 32, "NR RRC Encryption Key (k_nr_rrc_enc)");
|
|
|
|
|
logger.info(sec_cfg.k_nr_rrc_int.data(), 32, "NR RRC Integrity Key (k_nr_rrc_int)");
|
|
|
|
|
logger.info(sec_cfg.k_nr_up_enc.data(), 32, "NR UP Encryption Key (k_nr_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)
|
|
|
|
|
{
|
|
|
|
|
logger.info("Regenerating KeNB with PCI=0x%02x, DL-EARFCN=%d", new_pci, new_dl_earfcn);
|
|
|
|
|
logger.info(k_gnb, 32, "Old K_eNB (k_enb)");
|
|
|
|
|
logger.info("Regenerating KgNB with PCI=0x%02x, DL-EARFCN=%d", new_pci, new_dl_earfcn);
|
|
|
|
|
logger.info(k_gnb, 32, "Old K_gNB (k_enb)");
|
|
|
|
|
// Generate K_enb*
|
|
|
|
|
uint8_t k_gnb_star[32];
|
|
|
|
|
srsran::security_generate_k_enb_star(k_gnb, new_pci, new_dl_earfcn, k_gnb_star);
|
|
|
|
|