Added more 5G security kdfs

Added new 5G SIM functions

Added const parameters for security functions
master
David Rupprecht 3 years ago committed by David Rupprecht
parent a645d74eaf
commit a9a23214b0

@ -128,59 +128,79 @@ int kdf_common(const uint8_t fc,
const std::vector<uint8_t>& P3,
uint8_t* output);
uint8_t security_generate_k_asme(const uint8_t* ck,
const uint8_t* ik,
const uint8_t* ak_xor_sqn,
const uint16_t mcc,
const uint16_t mnc,
uint8_t* k_asme);
uint8_t security_generate_k_ausf(const uint8_t* ck,
const uint8_t* ik,
const uint8_t* ak_xor_sqn,
const char* serving_network_name,
uint8_t* k_ausf);
uint8_t security_generate_k_amf(const uint8_t* k_seaf,
const char* supi_,
const uint8_t* abba_,
const uint32_t abba_len,
uint8_t* k_amf);
uint8_t security_generate_k_seaf(const uint8_t* k_ausf, const char* serving_network_name, uint8_t* k_seaf);
uint8_t security_generate_k_enb(const uint8_t* k_asme, const uint32_t nas_count, uint8_t* k_enb);
uint8_t
security_generate_k_asme(uint8_t* ck, uint8_t* ik, uint8_t* ak_xor_sqn, uint16_t mcc, uint16_t mnc, uint8_t* k_asme);
uint8_t security_generate_k_ausf(uint8_t* ck,
uint8_t* ik,
uint8_t* ak_xor_sqn,
const char* serving_network_name,
uint8_t* k_ausf);
uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count, uint8_t* k_enb);
uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci, uint32_t earfcn, uint8_t* k_enb_star);
uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync, uint8_t* nh);
uint8_t security_generate_k_nas(uint8_t* k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int);
uint8_t security_generate_k_rrc(uint8_t* k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int);
uint8_t security_generate_k_up(uint8_t* k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int);
uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int);
uint8_t security_generate_k_nr_up(uint8_t* k_gnb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int);
uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count);
uint8_t security_generate_res_star(uint8_t* ck,
uint8_t* ik,
const char* serving_network_name,
uint8_t* rand,
uint8_t* res,
size_t res_len,
uint8_t* res_star);
security_generate_k_enb_star(const uint8_t* k_enb, const uint32_t pci, const uint32_t earfcn, uint8_t* k_enb_star);
uint8_t security_generate_nh(const uint8_t* k_asme, const uint8_t* sync, uint8_t* nh);
uint8_t security_generate_k_nas(const uint8_t* k_asme,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int);
uint8_t security_generate_k_nas_5g(const uint8_t* k_amf,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int);
uint8_t security_generate_k_rrc(const uint8_t* k_enb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int);
uint8_t security_generate_k_up(const uint8_t* k_enb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int);
uint8_t security_generate_k_nr_rrc(const uint8_t* k_gnb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int);
uint8_t security_generate_k_nr_up(const uint8_t* k_gnb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int);
uint8_t security_generate_sk_gnb(const uint8_t* k_enb, const uint16_t scg_count, uint8_t* sk_gnb);
uint8_t security_generate_res_star(const uint8_t* ck,
const uint8_t* ik,
const char* serving_network_name,
const uint8_t* rand,
const uint8_t* res,
const size_t res_len,
uint8_t* res_star);
/******************************************************************************
* Integrity Protection
*****************************************************************************/

@ -42,18 +42,26 @@ public:
uint8_t* res,
int* res_len,
uint8_t* k_asme) = 0;
virtual void generate_nas_keys(uint8_t* k_asme,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual bool generate_res_star(uint8_t* rand,
uint8_t* res,
int res_len,
const char* serving_network_name,
uint8_t* res_start,
uint32_t* res_star_len) = 0;
virtual auth_result_t generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf) = 0;
virtual void generate_nas_keys(uint8_t* k_asme,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual bool generate_nas_keys_5g(uint8_t* k_amf,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
};
// USIM interface for RRC

@ -58,8 +58,12 @@ namespace srsran {
* Key Generation
*****************************************************************************/
uint8_t
security_generate_k_asme(uint8_t* ck, uint8_t* ik, uint8_t* ak_xor_sqn_, uint16_t mcc, uint16_t mnc, uint8_t* k_asme)
uint8_t security_generate_k_asme(const uint8_t* ck,
const uint8_t* ik,
const uint8_t* ak_xor_sqn_,
const uint16_t mcc,
const uint16_t mnc,
uint8_t* k_asme)
{
if (ck == NULL || ik == NULL || ak_xor_sqn_ == NULL || k_asme == NULL) {
log_error("Invalid inputs");
@ -100,11 +104,11 @@ security_generate_k_asme(uint8_t* ck, uint8_t* ik, uint8_t* ak_xor_sqn_, uint16_
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_ausf(uint8_t* ck,
uint8_t* ik,
uint8_t* ak_xor_sqn_,
const char* serving_network_name,
uint8_t* k_ausf)
uint8_t security_generate_k_ausf(const uint8_t* ck,
const uint8_t* ik,
const uint8_t* ak_xor_sqn_,
const char* serving_network_name,
uint8_t* k_ausf)
{
if (ck == NULL || ik == NULL || ak_xor_sqn_ == NULL || serving_network_name == NULL || k_ausf == NULL) {
log_error("Invalid inputs");
@ -128,7 +132,7 @@ uint8_t security_generate_k_ausf(uint8_t* ck,
memcpy(ak_xor_sqn.data(), ak_xor_sqn_, ak_xor_sqn.size());
uint8_t output[32];
if (kdf_common(FC_5G_RES_STAR_DERIVATION, key, ssn, ak_xor_sqn, output) != SRSRAN_SUCCESS) {
if (kdf_common(FC_5G_KAUSF_DERIVATION, key, ssn, ak_xor_sqn, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
@ -137,7 +141,60 @@ uint8_t security_generate_k_ausf(uint8_t* ck,
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count_, uint8_t* k_enb)
uint8_t security_generate_k_seaf(const uint8_t* k_ausf, const char* serving_network_name, uint8_t* k_seaf)
{
if (k_ausf == NULL || serving_network_name == NULL || k_seaf == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_ausf, 32);
// Serving Network Name
std::vector<uint8_t> ssn;
ssn.resize(strlen(serving_network_name));
memcpy(ssn.data(), serving_network_name, ssn.size());
if (kdf_common(FC_5G_KSEAF_DERIVATION, key, ssn, k_seaf) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_amf(const uint8_t* k_seaf,
const char* supi_,
const uint8_t* abba_,
const uint32_t abba_len,
uint8_t* k_amf)
{
if (k_seaf == NULL || supi_ == NULL || abba_ == NULL || k_amf == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_seaf, 32);
// SUPI
std::vector<uint8_t> supi;
supi.resize(strlen(supi_));
memcpy(supi.data(), supi_, supi.size());
// ABBA
std::vector<uint8_t> abba;
abba.resize(abba_len);
memcpy(abba.data(), abba_, abba.size());
if (kdf_common(FC_5G_KAMF_DERIVATION, key, supi, abba, k_amf) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_enb(const uint8_t* k_asme, const uint32_t nas_count_, uint8_t* k_enb)
{
if (k_asme == NULL || k_enb == NULL) {
log_error("Invalid inputs");
@ -162,7 +219,8 @@ uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count_, uint8_t* k
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci_, uint32_t earfcn_, uint8_t* k_enb_star)
uint8_t
security_generate_k_enb_star(const uint8_t* k_enb, const uint32_t pci_, const uint32_t earfcn_, uint8_t* k_enb_star)
{
if (k_enb == NULL || k_enb_star == NULL) {
log_error("Invalid inputs");
@ -190,7 +248,7 @@ uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci_, uint32_t ear
return SRSRAN_SUCCESS;
}
uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync_, uint8_t* nh)
uint8_t security_generate_nh(const uint8_t* k_asme, const uint8_t* sync_, uint8_t* nh)
{
if (k_asme == NULL || sync_ == NULL || nh == NULL) {
log_error("Invalid inputs");
@ -211,11 +269,11 @@ uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync_, uint8_t* nh)
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nas(uint8_t* k_asme,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int)
uint8_t security_generate_k_nas(const uint8_t* k_asme,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int)
{
if (k_asme == NULL || k_nas_enc == NULL || k_nas_int == NULL) {
log_error("Invalid inputs");
@ -260,11 +318,60 @@ uint8_t security_generate_k_nas(uint8_t* k_asme,
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_rrc(uint8_t* k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
uint8_t security_generate_k_nas_5g(const uint8_t* k_amf,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_nas_enc,
uint8_t* k_nas_int)
{
if (k_amf == NULL || k_nas_enc == NULL || k_nas_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_amf, 32);
// Derive NAS ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_NAS_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive NAS INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_NAS_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive NAS int
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_rrc(const uint8_t* k_enb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
{
if (k_enb == NULL || k_rrc_enc == NULL || k_rrc_int == NULL) {
log_error("Invalid inputs");
@ -309,11 +416,11 @@ uint8_t security_generate_k_rrc(uint8_t* k_enb,
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_up(uint8_t* k_enb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int)
uint8_t security_generate_k_up(const uint8_t* k_enb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int)
{
if (k_enb == NULL || k_up_enc == NULL || k_up_int == NULL) {
log_error("Invalid inputs");
@ -358,7 +465,7 @@ uint8_t security_generate_k_up(uint8_t* k_enb,
return SRSRAN_SUCCESS;
}
uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count_)
uint8_t security_generate_sk_gnb(const uint8_t* k_enb, const uint16_t scg_count_, uint8_t* sk_gnb)
{
if (k_enb == NULL || sk_gnb == NULL) {
log_error("Invalid inputs");
@ -385,11 +492,11 @@ uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_c
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
uint8_t security_generate_k_nr_rrc(const uint8_t* k_gnb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
{
if (k_gnb == NULL || k_rrc_enc == NULL || k_rrc_int == NULL) {
log_error("Invalid inputs");
@ -434,11 +541,11 @@ uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb,
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nr_up(uint8_t* k_gnb,
CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int)
uint8_t security_generate_k_nr_up(const uint8_t* k_gnb,
const CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
const INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8_t* k_up_enc,
uint8_t* k_up_int)
{
if (k_gnb == NULL || k_up_enc == NULL || k_up_int == NULL) {
log_error("Invalid inputs");
@ -483,13 +590,13 @@ uint8_t security_generate_k_nr_up(uint8_t* k_gnb,
return SRSRAN_SUCCESS;
}
uint8_t security_generate_res_star(uint8_t* ck,
uint8_t* ik,
const char* serving_network_name,
uint8_t* rand_,
uint8_t* res_,
size_t res_len_,
uint8_t* res_star)
uint8_t security_generate_res_star(const uint8_t* ck,
const uint8_t* ik,
const char* serving_network_name,
const uint8_t* rand_,
const uint8_t* res_,
const size_t res_len_,
uint8_t* res_star)
{
if (ck == NULL || ik == NULL || serving_network_name == NULL || rand_ == NULL || res_ == NULL || res_star == NULL) {
log_error("Invalid inputs");

@ -40,7 +40,7 @@ int test_set_ksg()
0x9e, 0x5d, 0x28, 0xaf, 0x0e, 0x83, 0x22, 0xeb, 0x57, 0x3a, 0xda, 0x36, 0xf2, 0x1a, 0x5a, 0x89};
uint8_t sk_gnb_o[32];
uint16_t scg_counter = 0;
err_lte = srsran::security_generate_sk_gnb(k_enb, sk_gnb_o, scg_counter);
err_lte = srsran::security_generate_sk_gnb(k_enb, scg_counter, sk_gnb_o);
TESTASSERT(err_lte == SRSRAN_SUCCESS);
logger.info(&sk_gnb_o[0], sizeof(sk_gnb_o), "sk gnb o:");
uint8_t sk_gnb[] = {0x45, 0xcb, 0xc3, 0xf8, 0xa8, 0x11, 0x93, 0xfd, 0x5c, 0x52, 0x29, 0x30, 0x0d, 0x59, 0xed, 0xf8,
@ -298,12 +298,126 @@ int test_generate_res_star()
uint8_t res_star[] = {0xb0, 0xe3, 0x5b, 0x23, 0xdb, 0xd7, 0xa1, 0x8c, 0x84, 0x8b, 0xfa, 0xd9, 0x11, 0x35, 0xe3, 0xfd};
logger.info(res_star, 16, "RES STAR:");
logger.info(res_star_o, 16, "RES STAR:");
TESTASSERT(arrcmp(res_star_o, res_star, sizeof(res_star)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_ausf()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_ausf_o[32];
uint8_t ck[] = {0x56, 0x1e, 0x05, 0xef, 0xbd, 0xf2, 0xef, 0xeb, 0x2d, 0x55, 0x8f, 0x04, 0x1c, 0x53, 0xc4, 0x45};
uint8_t ik[] = {0x01, 0xe0, 0xf2, 0xf5, 0x53, 0x54, 0x31, 0x31, 0x2d, 0x57, 0x27, 0x98, 0x14, 0xcf, 0xcd, 0x89};
uint8_t ak_xor_sqn[] = {0x30, 0x5e, 0xb0, 0x6b, 0x73, 0x07};
std::string ssn = "5G:mnc070.mcc901.3gppnetwork.org";
TESTASSERT(srsran::security_generate_k_ausf(ck, ik, ak_xor_sqn, ssn.c_str(), k_ausf_o) == SRSRAN_SUCCESS);
uint8_t k_ausf[] = {0xa2, 0xce, 0xb2, 0x0f, 0x79, 0x28, 0xbf, 0x15, 0x4d, 0x4b, 0x54, 0x8a, 0xee, 0x6d, 0x10, 0xa9,
0x76, 0x01, 0x84, 0x7f, 0xd7, 0x2d, 0x2b, 0xc9, 0x01, 0x98, 0x2c, 0x08, 0x6e, 0xa0, 0xf3, 0x46};
// TODO check the out put with k AMF
logger.info(k_ausf_o, 32, "K AUSF:");
TESTASSERT(arrcmp(k_ausf_o, k_ausf, sizeof(k_ausf)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_seaf()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_seaf_o[32];
uint8_t k_ausf[] = {0xd9, 0xc8, 0xff, 0x91, 0xb6, 0x9e, 0x25, 0x0e, 0x25, 0x6e, 0x92, 0x46, 0x6a, 0xcf, 0x80, 0xa1,
0xd8, 0x2b, 0x65, 0xf0, 0x94, 0xb7, 0xc0, 0x71, 0x19, 0x9c, 0x03, 0x12, 0xe0, 0x67, 0xff, 0x3b};
std::string ssn = "5G:mnc070.mcc901.3gppnetwork.org";
TESTASSERT(srsran::security_generate_k_seaf(k_ausf, ssn.c_str(), k_seaf_o) == SRSRAN_SUCCESS);
uint8_t k_seaf[] = {0x6c, 0x50, 0xbf, 0xa5, 0xf3, 0x2a, 0x89, 0xad, 0xe1, 0xee, 0x6c, 0x70, 0x7d, 0xe6, 0xdc, 0xfe,
0xa0, 0x79, 0x0a, 0xfb, 0x6d, 0x14, 0xf9, 0xe5, 0x59, 0x43, 0xae, 0xda, 0x58, 0x33, 0x45, 0x48};
logger.info(k_seaf_o, 32, "K SEAF:");
TESTASSERT(arrcmp(k_seaf_o, k_seaf, sizeof(k_seaf)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_amf()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_amf_o[32];
uint8_t k_seaf[] = {0x6c, 0x50, 0xbf, 0xa5, 0xf3, 0x2a, 0x89, 0xad, 0xe1, 0xee, 0x6c, 0x70, 0x7d, 0xe6, 0xdc, 0xfe,
0xa0, 0x79, 0x0a, 0xfb, 0x6d, 0x14, 0xf9, 0xe5, 0x59, 0x43, 0xae, 0xda, 0x58, 0x33, 0x45, 0x48};
uint8_t abba[] = {0x00, 0x00};
std::string supi = "901700000021309";
TESTASSERT(srsran::security_generate_k_amf(k_seaf, supi.c_str(), abba, sizeof(abba), k_amf_o) == SRSRAN_SUCCESS);
uint8_t k_amf[] = {0x46, 0x23, 0x7e, 0xf0, 0x51, 0xd6, 0xa1, 0x6a, 0x39, 0x27, 0x52, 0x5f, 0xa6, 0x5c, 0xc3, 0x95,
0x44, 0xcd, 0xfd, 0x79, 0x90, 0xb9, 0x46, 0xad, 0x79, 0x65, 0x30, 0xe6, 0xd7, 0x87, 0xa0, 0xda};
logger.info(k_amf_o, 32, "K AMF:");
TESTASSERT(arrcmp(k_amf_o, k_amf, sizeof(k_amf)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_amf_2()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_amf_o[32];
uint8_t k_seaf[] = {0x30, 0x2a, 0xb7, 0xc9, 0x4f, 0xae, 0x97, 0xe0, 0x43, 0xb3, 0x70, 0xd3, 0xeb, 0x1f, 0x54, 0x68,
0xf6, 0xa1, 0xd4, 0x55, 0xd6, 0x56, 0xa4, 0xca, 0xb3, 0x51, 0xea, 0xcf, 0xb9, 0xf7, 0xe1, 0x36};
uint8_t abba[] = {0x00, 0x00};
std::string supi = "001010123456780";
TESTASSERT(srsran::security_generate_k_amf(k_seaf, supi.c_str(), abba, sizeof(abba), k_amf_o) == SRSRAN_SUCCESS);
uint8_t k_amf[] = {0x8f, 0x2a, 0x5d, 0x6c, 0x12, 0x60, 0x8d, 0x8a, 0x0a, 0x8d, 0x33, 0x0a, 0x71, 0x9d, 0xee, 0x07,
0x22, 0x6b, 0x47, 0x41, 0x7b, 0x66, 0x1a, 0xf5, 0x84, 0x90, 0xea, 0xb0, 0x7a, 0xa4, 0x37, 0xa4};
logger.info(k_amf_o, 32, "K AMF:");
TESTASSERT(arrcmp(k_amf_o, k_amf, sizeof(k_amf)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_nas_5g()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_nas_int_o[32];
uint8_t k_nas_enc_o[32];
uint8_t k_amf[] = {0x7d, 0x86, 0x18, 0x52, 0xb4, 0x2a, 0x86, 0xb5, 0x96, 0xfe, 0x22, 0xc8, 0xf5, 0x0b, 0x9b, 0x89,
0x5a, 0x1e, 0x21, 0x71, 0x6b, 0x61, 0xb8, 0xd1, 0x22, 0x78, 0x5e, 0x25, 0xba, 0xfc, 0x0d, 0x07};
TESTASSERT(srsran::security_generate_k_nas_5g(k_amf,
srsran::CIPHERING_ALGORITHM_ID_ENUM::CIPHERING_ALGORITHM_ID_EEA0,
srsran::INTEGRITY_ALGORITHM_ID_ENUM::INTEGRITY_ALGORITHM_ID_128_EIA2,
k_nas_enc_o,
k_nas_int_o) == SRSRAN_SUCCESS);
uint8_t k_nas_enc[] = {0x83, 0x85, 0x6a, 0x01, 0x81, 0x59, 0x55, 0x21, 0xc9, 0xd3, 0x2a,
0x19, 0x3f, 0x59, 0xc8, 0xa8, 0xfc, 0x7e, 0x99, 0xb9, 0x8b, 0x8c,
0x04, 0x20, 0x1f, 0x4f, 0x9d, 0x81, 0x43, 0x3b, 0x6b, 0x38};
uint8_t k_nas_int[] = {0x25, 0xc5, 0x8e, 0x27, 0xe7, 0xd2, 0xc4, 0x95, 0xf3, 0xd7, 0x35,
0x29, 0x3a, 0x82, 0xbf, 0xfa, 0xa5, 0x3e, 0xe8, 0x84, 0xb9, 0x8d,
0x36, 0x6b, 0x02, 0x89, 0x23, 0x1e, 0xc4, 0x19, 0x1e, 0xd3};
logger.info(k_nas_enc_o, 32, "k_nas_enc_o:");
TESTASSERT(arrcmp(k_nas_enc_o, k_nas_enc, sizeof(k_nas_enc)) == 0);
logger.info(k_nas_int_o, 32, "k_nas_int_o:");
TESTASSERT(arrcmp(k_nas_int_o, k_nas_int, sizeof(k_nas_int)) == 0);
return SRSRAN_SUCCESS;
}
int main(int argc, char** argv)
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
@ -321,6 +435,11 @@ int main(int argc, char** argv)
TESTASSERT(test_generate_k_nh() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_res_star() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_ausf() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_seaf() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_amf() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_amf_2() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_nas_5g() == SRSRAN_SUCCESS);
TESTASSERT(test_set_ksg() == SRSRAN_SUCCESS);
TESTASSERT(test_set_nr_rrc_up() == SRSRAN_SUCCESS);

@ -44,7 +44,14 @@ public:
uint8_t* res,
int* res_len,
uint8_t* k_asme);
// NAS interface
auth_result_t generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf);
// Helpers
virtual std::string get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str) final;

@ -36,21 +36,18 @@ public:
int* res_len,
uint8_t* k_asme);
auth_result_t generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf);
private:
auth_result_t gen_auth_res_milenage(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme);
auth_result_t gen_auth_res_xor(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme);
auth_result_t
gen_auth_res_milenage(uint8_t* rand, uint8_t* autn_enb, uint8_t* res, int* res_len, uint8_t* ak_xor_sqn);
auth_result_t gen_auth_res_xor(uint8_t* rand, uint8_t* autn_enb, uint8_t* res, int* res_len, uint8_t* ak_xor_sqn);
// Helpers
virtual std::string get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str) final;

@ -101,12 +101,19 @@ public:
bool update_nr_context(srsran::as_security_config_t* sec_cfg) final;
// 5G NAS interface
bool generate_res_star(uint8_t* rand,
uint8_t* res,
int res_len,
const char* serving_network_name,
uint8_t* res_start,
uint32_t* res_star_len) final;
virtual auth_result_t generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf) = 0;
bool generate_nas_keys_5g(uint8_t* k_amf,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
// Helpers
std::string get_mcc_str(const uint8_t* imsi_vec);
virtual std::string get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str) = 0;

@ -151,6 +151,76 @@ auth_result_t pcsc_usim::generate_authentication_response(uint8_t* rand,
return ret;
}
auth_result_t pcsc_usim::generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf)
{
uint8_t res[16];
uint8_t k_ausf[32];
uint8_t k_seaf[32];
int res_len;
auth_result_t ret = AUTH_FAILED;
if (!initiated) {
ERROR("USIM not initiated!");
return ret;
}
// Use RAND and AUTN to compute RES, CK, IK using SIM card
switch (sc.umts_auth(rand, autn_enb, res, &res_len, ik, ck, auts)) {
case 0:
logger.info("SCARD: USIM authentication successful.");
break;
case -1:
logger.error("SCARD: Failure during USIM UMTS authentication");
return ret;
case -2:
logger.info("SCARD: USIM synchronization failure, AUTS generated");
logger.debug(auts, AKA_AUTS_LEN, "AUTS");
memcpy(res, auts, AKA_AUTS_LEN);
res_len = AKA_AUTS_LEN;
return AUTH_SYNCH_FAILURE;
default:
logger.warning("SCARD: Unknown USIM failure.");
return ret;
}
// TODO: Extract ak and seq from auts
memset(ak, 0x00, AK_LEN);
// Extract sqn from autn
uint8_t sqn[SQN_LEN];
for (int i = 0; i < 6; i++) {
sqn[i] = autn_enb[i] ^ ak[i];
}
// Generate K_asme
logger.debug(ck, CK_LEN, "CK:");
logger.debug(ik, IK_LEN, "IK:");
logger.debug(ak, AK_LEN, "AK:");
logger.debug(sqn, SQN_LEN, "SQN:");
logger.debug("SSN=%s", serving_network_name);
// Generate RES STAR
security_generate_res_star(ck, ik, serving_network_name, rand, res, res_len, res_star);
logger.debug(res_star, 16, "RES STAR");
// Generate K_ausf
security_generate_k_ausf(ck, ik, sqn, serving_network_name, k_ausf);
logger.debug(k_ausf, 32, "K AUSF");
// Generate K_seaf
security_generate_k_seaf(k_ausf, serving_network_name, k_seaf);
logger.debug(k_seaf, 32, "K SEAF");
// Generate K_seaf
security_generate_k_amf(k_ausf, imsi_str.c_str(), abba, abba_len, k_amf);
logger.debug(k_amf, 32, "K AMF");
ret = AUTH_OK;
return ret;
}
std::string pcsc_usim::get_mnc_str(const uint8_t* imsi_vec, std::string mcc_str)
{
uint32_t mcc_len = 3;

@ -101,24 +101,68 @@ auth_result_t usim::generate_authentication_response(uint8_t* rand,
int* res_len,
uint8_t* k_asme_)
{
auth_result_t auth_result;
uint8_t ak_xor_sqn[6];
if (auth_algo_xor == auth_algo) {
auth_result = gen_auth_res_xor(rand, autn_enb, res, res_len, ak_xor_sqn);
} else {
auth_result = gen_auth_res_milenage(rand, autn_enb, res, res_len, ak_xor_sqn);
}
if (auth_result == AUTH_OK) {
// Generate K_asme
security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme_);
}
return auth_result;
}
auth_result_t usim::generate_authentication_response_5g(uint8_t* rand,
uint8_t* autn_enb,
const char* serving_network_name,
uint8_t* abba,
uint32_t abba_len,
uint8_t* res_star,
uint8_t* k_amf)
{
auth_result_t auth_result;
uint8_t ak_xor_sqn[6];
uint8_t res[16];
uint8_t k_ausf[32];
uint8_t k_seaf[32];
int res_len;
if (auth_algo_xor == auth_algo) {
return gen_auth_res_xor(rand, autn_enb, mcc, mnc, res, res_len, k_asme_);
auth_result = gen_auth_res_xor(rand, autn_enb, res, &res_len, ak_xor_sqn);
} else {
return gen_auth_res_milenage(rand, autn_enb, mcc, mnc, res, res_len, k_asme_);
auth_result = gen_auth_res_milenage(rand, autn_enb, res, &res_len, ak_xor_sqn);
}
if (auth_result == AUTH_OK) {
// Generate RES STAR
security_generate_res_star(ck, ik, serving_network_name, rand, res, res_len, res_star);
logger.debug(res_star, 16, "RES STAR");
// Generate K_ausf
security_generate_k_ausf(ck, ik, ak_xor_sqn, serving_network_name, k_ausf);
logger.debug(k_ausf, 32, "K AUSF");
// Generate K_seaf
security_generate_k_seaf(k_ausf, serving_network_name, k_seaf);
logger.debug(k_seaf, 32, "K SEAF");
// Generate K_seaf
logger.debug(abba, abba_len, "ABBA:");
logger.debug("IMSI: %s", imsi_str.c_str());
security_generate_k_amf(k_seaf, imsi_str.c_str(), abba, abba_len, k_amf);
logger.debug(k_amf, 32, "K AMF");
}
return auth_result;
}
/*******************************************************************************
Helpers
*******************************************************************************/
auth_result_t usim::gen_auth_res_milenage(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme)
auth_result_t
usim::gen_auth_res_milenage(uint8_t* rand, uint8_t* autn_enb, uint8_t* res, int* res_len, uint8_t* ak_xor_sqn)
{
auth_result_t result = AUTH_OK;
uint32_t i;
@ -159,24 +203,22 @@ auth_result_t usim::gen_auth_res_milenage(uint8_t* rand,
}
}
uint8_t ak_xor_sqn[6];
for (i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme);
logger.debug(ck, CK_LEN, "CK:");
logger.debug(ik, IK_LEN, "IK:");
logger.debug(ak, AK_LEN, "AK:");
logger.debug(sqn, 6, "sqn:");
logger.debug(amf, 2, "amf:");
logger.debug(mac, 8, "mac:");
return result;
}
// 3GPP TS 34.108 version 10.0.0 Section 8
auth_result_t usim::gen_auth_res_xor(uint8_t* rand,
uint8_t* autn_enb,
uint16_t mcc,
uint16_t mnc,
uint8_t* res,
int* res_len,
uint8_t* k_asme_)
auth_result_t usim::gen_auth_res_xor(uint8_t* rand, uint8_t* autn_enb, uint8_t* res, int* res_len, uint8_t* ak_xor_sqn)
{
auth_result_t result = AUTH_OK;
uint8_t sqn[6];
@ -230,14 +272,10 @@ auth_result_t usim::gen_auth_res_xor(uint8_t* rand,
logger.debug(amf, 2, "amf:");
logger.debug(mac, 8, "mac:");
uint8_t ak_xor_sqn[6];
for (uint32_t i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme_);
return result;
}

@ -348,6 +348,21 @@ void usim_base::restore_keys_from_failed_ho(srsran::as_security_config_t* as_ctx
return;
}
bool usim_base::generate_nas_keys_5g(uint8_t* k_amf,
uint8_t* k_nas_enc,
uint8_t* k_nas_int,
srsran::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srsran::INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
{
if (!initiated) {
logger.error("USIM not initiated!");
return false;
}
// Generate K_nas_enc and K_nas_int
security_generate_k_nas_5g(k_amf, cipher_algo, integ_algo, k_nas_enc, k_nas_int);
return true;
}
/*
* NR RRC Interface
*/
@ -360,7 +375,7 @@ bool usim_base::generate_nr_context(uint16_t sk_counter, srsran::as_security_con
}
logger.info("Generating Keys. SCG Counter %d", sk_counter);
srsran::security_generate_sk_gnb(k_enb_ctx.k_enb.data(), k_gnb_ctx.sk_gnb.data(), sk_counter);
srsran::security_generate_sk_gnb(k_enb_ctx.k_enb.data(), sk_counter, k_gnb_ctx.sk_gnb.data());
logger.info(k_gnb_ctx.sk_gnb.data(), 32, "k_sk_gnb");
if (update_nr_context(sec_cfg) == false) {
return false;
@ -396,30 +411,4 @@ bool usim_base::update_nr_context(srsran::as_security_config_t* sec_cfg)
return true;
}
bool usim_base::generate_res_star(uint8_t* rand,
uint8_t* res,
int res_len,
const char* serving_network_name,
uint8_t* res_star,
uint32_t* res_star_len)
{
if (!initiated) {
logger.error("USIM not initiated!");
return false;
}
logger.info("Generate res_star");
logger.info(rand, 16, "RAND");
logger.info(res, res_len, "RES");
logger.info(
(uint8_t*)serving_network_name, strlen(serving_network_name), "Serving Network Name %s", serving_network_name);
srsran::security_generate_res_star(ck, ik, serving_network_name, rand, res, res_len, res_star);
*res_star_len = 16;
logger.info(res_star, *res_star_len, "res_star");
return true;
}
} // namespace srsue

Loading…
Cancel
Save