Created k_enb_context structure that holds k_enb, NCC and NH to make it easier to restore context from failed handover.

master
Pedro Alvarez 4 years ago committed by Francisco Paisana
parent bcb422736c
commit 5a4e71a6e4

@ -62,6 +62,13 @@ typedef enum {
static const char security_direction_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"Uplink", "Downlink"}; static const char security_direction_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"Uplink", "Downlink"};
using as_key_t = std::array<uint8_t, 32>; using as_key_t = std::array<uint8_t, 32>;
struct k_enb_context_t {
as_key_t k_enb;
as_key_t nh;
bool is_first_ncc;
uint32_t ncc;
};
struct as_security_config_t { struct as_security_config_t {
as_key_t k_rrc_int; as_key_t k_rrc_int;
as_key_t k_rrc_enc; as_key_t k_rrc_enc;

@ -123,21 +123,16 @@ protected:
uint8_t ik[IK_LEN] = {}; uint8_t ik[IK_LEN] = {};
uint8_t ak[AK_LEN] = {}; uint8_t ak[AK_LEN] = {};
uint8_t k_asme[KEY_LEN] = {}; uint8_t k_asme[KEY_LEN] = {};
uint8_t nh[KEY_LEN] = {};
uint8_t k_enb[KEY_LEN] = {};
uint8_t k_enb_star[KEY_LEN] = {}; uint8_t k_enb_star[KEY_LEN] = {};
uint8_t k_enb_initial[KEY_LEN] = {}; uint8_t k_enb_initial[KEY_LEN] = {};
uint8_t auts[AKA_AUTS_LEN] = {}; uint8_t auts[AKA_AUTS_LEN] = {};
// Current K_eNB context (K_eNB, NH and NCC)
srslte::k_enb_context_t k_enb_ctx = {};
// Helpers to restore security context if HO fails // Helpers to restore security context if HO fails
bool old_is_first_ncc = false; srslte::k_enb_context_t old_k_enb_ctx = {};
uint8_t old_k_enb[32] = {}; srslte::as_security_config_t old_as_ctx = {};
uint8_t old_nh[32] = {};
uint8_t old_ncc = {};
srslte::as_security_config_t old_as_ctx = {};
uint32_t current_ncc = 0;
bool is_first_ncc = false;
}; };
} // namespace srsue } // namespace srsue

@ -159,25 +159,35 @@ void usim_base::generate_as_keys(uint8_t* k_asme_, uint32_t count_ul, srslte::as
log->debug_hex(k_asme_, 32, "K_asme"); log->debug_hex(k_asme_, 32, "K_asme");
// Generate K_enb // Generate K_enb
srslte::security_generate_k_enb(k_asme_, count_ul, k_enb); srslte::security_generate_k_enb(k_asme_, count_ul, k_enb_ctx.k_enb.data());
memcpy(k_asme, k_asme_, 32); memcpy(k_asme, k_asme_, 32);
// Save initial k_enb // Save initial k_enb
memcpy(k_enb_initial, k_enb, 32); memcpy(k_enb_initial, k_enb_ctx.k_enb.data(), 32);
// Generate K_rrc_enc and K_rrc_int // Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc( security_generate_k_rrc(k_enb_ctx.k_enb.data(),
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_int.data()); 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 // Generate K_up_enc and K_up_int
security_generate_k_up( security_generate_k_up(k_enb_ctx.k_enb.data(),
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data()); sec_cfg->cipher_algo,
sec_cfg->integ_algo,
current_ncc = 0; sec_cfg->k_up_enc.data(),
is_first_ncc = true; sec_cfg->k_up_int.data());
log->debug_hex(k_enb, 32, "Initial K_eNB"); k_enb_ctx.ncc = 0;
k_enb_ctx.is_first_ncc = true;
log->debug_hex(k_enb_ctx.k_enb.data(), 32, "Initial K_eNB");
log->debug_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "K_RRC_enc");
log->debug_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "K_RRC_enc");
log->debug_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "K_RRC_int");
log->debug_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "K_RRC_int");
} }
void usim_base::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg) void usim_base::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg)
@ -188,76 +198,79 @@ void usim_base::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srsl
} }
log->info("Re-generating AS Keys. PCI 0x%02x, DL-EARFCN %d, NCC %d\n", pci, earfcn, ncc); log->info("Re-generating AS Keys. PCI 0x%02x, DL-EARFCN %d, NCC %d\n", pci, earfcn, ncc);
log->info_hex(k_enb, 32, "Old K_eNB"); log->info_hex(k_enb_ctx.k_enb.data(), 32, "Old K_eNB");
uint8_t* enb_star_key = k_enb; uint8_t* enb_star_key = k_enb_ctx.k_enb.data();
if (ncc < 0) { if (ncc < 0) {
ncc = current_ncc; ncc = k_enb_ctx.ncc;
} }
while (current_ncc != (uint32_t)ncc) { while (k_enb_ctx.ncc != (uint32_t)ncc) {
uint8_t* sync = NULL; uint8_t* sync = nullptr;
if (is_first_ncc) { if (k_enb_ctx.is_first_ncc) {
log->debug("Using K_enb_initial for sync. 0x%02x, DL-EARFCN %d, NCC %d\n", pci, earfcn, current_ncc); log->debug("Using K_enb_initial for sync. 0x%02x, DL-EARFCN %d, NCC used: %d\n", pci, earfcn, k_enb_ctx.ncc);
sync = k_enb_initial; sync = k_enb_initial;
is_first_ncc = false; k_enb_ctx.is_first_ncc = false;
} else { } else {
log->debug("Using NH for sync. 0x%02x, DL-EARFCN %d, NCC %d\n", pci, earfcn, current_ncc); log->debug("Using NH for sync. 0x%02x, DL-EARFCN %d, NCC %d\n", pci, earfcn, k_enb_ctx.ncc);
sync = nh; sync = k_enb_ctx.nh.data();
} }
log->debug_hex(k_enb_ctx.nh.data(), 32, "NH:");
// Generate NH // Generate NH
srslte::security_generate_nh(k_asme, sync, nh); srslte::security_generate_nh(k_asme, sync, k_enb_ctx.nh.data());
current_ncc++; k_enb_ctx.ncc++;
if (current_ncc == 8) { if (k_enb_ctx.ncc == 8) {
current_ncc = 0; k_enb_ctx.ncc = 0;
} }
enb_star_key = nh; enb_star_key = k_enb_ctx.nh.data();
} }
// Generate K_enb // Generate K_enb
srslte::security_generate_k_enb_star(enb_star_key, pci, earfcn, k_enb_star); srslte::security_generate_k_enb_star(enb_star_key, pci, earfcn, k_enb_star);
// K_enb becomes K_enb* // K_enb becomes K_enb*
memcpy(k_enb, k_enb_star, 32); memcpy(k_enb_ctx.k_enb.data(), k_enb_star, 32);
// Generate K_rrc_enc and K_rrc_int // Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc( security_generate_k_rrc(k_enb_ctx.k_enb.data(),
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_int.data()); 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 // Generate K_up_enc and K_up_int
security_generate_k_up( security_generate_k_up(k_enb_ctx.k_enb.data(),
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data()); sec_cfg->cipher_algo,
sec_cfg->integ_algo,
sec_cfg->k_up_enc.data(),
sec_cfg->k_up_int.data());
log->info_hex(k_enb, 32, "HO K_eNB"); log->info_hex(k_enb_ctx.k_enb.data(), 32, "HO K_eNB");
log->info_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "HO K_RRC_enc"); log->info_hex(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "HO K_RRC_enc");
log->info_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "HO K_RRC_int"); log->info_hex(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "HO K_RRC_int");
} }
void usim_base::store_keys_before_ho(const srslte::as_security_config_t& as_ctx) void usim_base::store_keys_before_ho(const srslte::as_security_config_t& as_ctx)
{ {
log->info("Storing AS Keys pre-handover. NCC=%d\n", current_ncc); log->info("Storing AS Keys pre-handover. NCC=%d\n", k_enb_ctx.ncc);
log->info_hex(k_enb, 32, "Old K_eNB"); log->info_hex(k_enb_ctx.k_enb.data(), 32, "Old K_eNB");
log->info_hex(as_ctx.k_rrc_enc.data(), as_ctx.k_rrc_enc.size(), "Old K_RRC_enc"); log->info_hex(as_ctx.k_rrc_enc.data(), as_ctx.k_rrc_enc.size(), "Old K_RRC_enc");
log->info_hex(as_ctx.k_rrc_enc.data(), as_ctx.k_rrc_enc.size(), "Old K_RRC_enc"); log->info_hex(as_ctx.k_rrc_enc.data(), as_ctx.k_rrc_enc.size(), "Old K_RRC_enc");
log->info_hex(as_ctx.k_rrc_int.data(), as_ctx.k_rrc_int.size(), "Old K_RRC_int"); log->info_hex(as_ctx.k_rrc_int.data(), as_ctx.k_rrc_int.size(), "Old K_RRC_int");
log->info_hex(as_ctx.k_rrc_int.data(), as_ctx.k_rrc_int.size(), "Old K_RRC_int"); log->info_hex(as_ctx.k_rrc_int.data(), as_ctx.k_rrc_int.size(), "Old K_RRC_int");
old_is_first_ncc = is_first_ncc; old_k_enb_ctx = k_enb_ctx;
old_as_ctx = as_ctx; old_as_ctx = as_ctx;
old_ncc = current_ncc;
memcpy(old_nh, nh, 32);
memcpy(old_k_enb, k_enb, 32);
return; return;
} }
void usim_base::restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx) void usim_base::restore_keys_from_failed_ho(srslte::as_security_config_t* as_ctx)
{ {
log->info("Restoring Keys from failed handover. NCC=%d\n", old_ncc); log->info("Restoring Keys from failed handover. NCC=%d\n", old_k_enb_ctx.ncc);
*as_ctx = old_as_ctx; *as_ctx = old_as_ctx;
current_ncc = old_ncc; k_enb_ctx = old_k_enb_ctx;
is_first_ncc = old_is_first_ncc;
memcpy(nh, old_nh, 32);
memcpy(k_enb, old_k_enb, 32);
return; return;
} }

Loading…
Cancel
Save