Commit 8baa1fe0 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'fix_naked_ptr_security_ctx' into 'develop'

Fix naked ptr for NAS security context

See merge request oai/cn5g/oai-cn5g-amf!200
parents f659ec6b 2cb03dbe
...@@ -218,17 +218,17 @@ void amf_n1::handle_itti_message(itti_downlink_nas_transfer& itti_msg) { ...@@ -218,17 +218,17 @@ void amf_n1::handle_itti_message(itti_downlink_nas_transfer& itti_msg) {
amf_ue_ngap_id); amf_ue_ngap_id);
return; return;
} }
nas_secu_ctx* secu = nc->security_ctx;
if (!secu) { if (!nc->security_ctx.has_value()) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return; return;
} }
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK, nc->security_ctx.value(), false, INTEGRITY_PROTECTED_AND_CIPHERED,
(uint8_t*) bdata(itti_msg.dl_nas), blength(itti_msg.dl_nas), NAS_MESSAGE_DOWNLINK, (uint8_t*) bdata(itti_msg.dl_nas),
protected_nas); blength(itti_msg.dl_nas), protected_nas);
if (itti_msg.is_n2sm_set) { if (itti_msg.is_n2sm_set) {
// PDU Session Resource Release Command // PDU Session Resource Release Command
...@@ -316,19 +316,25 @@ void amf_n1::handle_itti_message(itti_downlink_nas_transfer& itti_msg) { ...@@ -316,19 +316,25 @@ void amf_n1::handle_itti_message(itti_downlink_nas_transfer& itti_msg) {
} }
} else { } else {
// send using InitialContextSetupRequest // send using InitialContextSetupRequest
uint8_t* kamf = nc->kamf[secu->vector_pointer]; uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS];
uint8_t kgnb[32]; uint8_t kgnb[AUTH_VECTOR_LENGTH_OCTETS];
uint32_t ulcount = if (!nc->get_kamf(nc->security_ctx.value().vector_pointer, kamf)) {
secu->ul_count.seq_num | (secu->ul_count.overflow << 8); Logger::amf_n1().warn("No Kamf found");
Authentication_5gaka::derive_kgnb(0, 0x01, kamf, kgnb); return;
output_wrapper::print_buffer("amf_n1", "Kamf", kamf, 32); }
uint32_t ulcount = nc->security_ctx.value().ul_count.seq_num |
(nc->security_ctx.value().ul_count.overflow << 8);
Authentication_5gaka::derive_kgnb(
0, 0x01, kamf, kgnb); // TODO: remove hardcoded value
output_wrapper::print_buffer(
"amf_n1", "Kamf", kamf, AUTH_VECTOR_LENGTH_OCTETS);
std::shared_ptr<itti_initial_context_setup_request> csr = std::shared_ptr<itti_initial_context_setup_request> csr =
std::make_shared<itti_initial_context_setup_request>( std::make_shared<itti_initial_context_setup_request>(
TASK_AMF_N1, TASK_AMF_N2); TASK_AMF_N1, TASK_AMF_N2);
csr->ran_ue_ngap_id = ran_ue_ngap_id; csr->ran_ue_ngap_id = ran_ue_ngap_id;
csr->amf_ue_ngap_id = amf_ue_ngap_id; csr->amf_ue_ngap_id = amf_ue_ngap_id;
csr->kgnb = blk2bstr(kgnb, 32); csr->kgnb = blk2bstr(kgnb, AUTH_VECTOR_LENGTH_OCTETS);
csr->nas = protected_nas; csr->nas = protected_nas;
csr->pdu_session_id = itti_msg.pdu_session_id; csr->pdu_session_id = itti_msg.pdu_session_id;
csr->is_pdu_exist = true; csr->is_pdu_exist = true;
...@@ -460,14 +466,14 @@ void amf_n1::handle_itti_message(itti_uplink_nas_data_ind& nas_data_ind) { ...@@ -460,14 +466,14 @@ void amf_n1::handle_itti_message(itti_uplink_nas_data_ind& nas_data_ind) {
"Abnormal condition: NAS context does not exist ..."); "Abnormal condition: NAS context does not exist ...");
return; return;
} }
if (!nc->security_ctx) { if (!nc->security_ctx.has_value()) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return; return;
} }
uint32_t mac32 = 0; uint32_t mac32 = 0;
if (!nas_message_integrity_protected( if (!nas_message_integrity_protected(
nc->security_ctx, NAS_MESSAGE_UPLINK, nc->security_ctx.value(), NAS_MESSAGE_UPLINK,
(uint8_t*) bdata(received_nas_msg) + 6, (uint8_t*) bdata(received_nas_msg) + 6,
blength(received_nas_msg) - 6, mac32)) { blength(received_nas_msg) - 6, mac32)) {
Logger::amf_n1().debug("IA0_5G"); Logger::amf_n1().debug("IA0_5G");
...@@ -481,7 +487,7 @@ void amf_n1::handle_itti_message(itti_uplink_nas_data_ind& nas_data_ind) { ...@@ -481,7 +487,7 @@ void amf_n1::handle_itti_message(itti_uplink_nas_data_ind& nas_data_ind) {
if (mac32 == mac32_recv) { if (mac32 == mac32_recv) {
isMatched = true; isMatched = true;
Logger::amf_n1().debug("Integrity matched"); Logger::amf_n1().debug("Integrity matched");
// nc->security_ctx->ul_count.seq_num ++; // nc->security_ctx.value().ul_count.seq_num ++;
} }
if (!isMatched) { if (!isMatched) {
Logger::amf_n1().error("Received message not integrity matched"); Logger::amf_n1().error("Received message not integrity matched");
...@@ -493,7 +499,7 @@ void amf_n1::handle_itti_message(itti_uplink_nas_data_ind& nas_data_ind) { ...@@ -493,7 +499,7 @@ void amf_n1::handle_itti_message(itti_uplink_nas_data_ind& nas_data_ind) {
(uint8_t*) bdata(received_nas_msg) + 7, (uint8_t*) bdata(received_nas_msg) + 7,
blength(received_nas_msg) - 7); blength(received_nas_msg) - 7);
if (!nas_message_cipher_protected( if (!nas_message_cipher_protected(
nc->security_ctx, NAS_MESSAGE_UPLINK, ciphered, nc->security_ctx.value(), NAS_MESSAGE_UPLINK, ciphered,
decoded_plain_msg)) { decoded_plain_msg)) {
Logger::amf_n1().error("Decrypt NAS message failure"); Logger::amf_n1().error("Decrypt NAS message failure");
bdestroy_wrapper(&ciphered); bdestroy_wrapper(&ciphered);
...@@ -586,12 +592,13 @@ void amf_n1::nas_signalling_establishment_request_handle( ...@@ -586,12 +592,13 @@ void amf_n1::nas_signalling_establishment_request_handle(
Logger::amf_n1().error("No NAS Context found"); Logger::amf_n1().error("No NAS Context found");
return; return;
} }
/* if (!nc->security_ctx) { /* if (!nc->security_ctx.has_value()) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return; return;
} }
*/ */
if (nc && nc->security_ctx) nc->security_ctx->ul_count.seq_num = ulCount; if (nc && nc->security_ctx.has_value())
nc->security_ctx.value().ul_count.seq_num = ulCount;
service_request_handle(nc, ran_ue_ngap_id, amf_ue_ngap_id, plain_msg); service_request_handle(nc, ran_ue_ngap_id, amf_ue_ngap_id, plain_msg);
} break; } break;
...@@ -836,13 +843,15 @@ void amf_n1::service_request_handle( ...@@ -836,13 +843,15 @@ void amf_n1::service_request_handle(
"GUTI %s, 5G-TMSI %s", guti.c_str(), tmsi.c_str()); "GUTI %s, 5G-TMSI %s", guti.c_str(), tmsi.c_str());
std::shared_ptr<nas_context> old_nc = {}; std::shared_ptr<nas_context> old_nc = {};
if (guti_2_nas_context(guti, old_nc)) { if (guti_2_nas_context(guti, old_nc)) {
// nc->security_ctx = old_nc->security_ctx; // nc->security_ctx =
// std::make_optional<nas_secu_ctx>(old_nc->security_ctx.value);
} }
} }
} }
// If there's no appropriate context, send Service Reject // If there's no appropriate context, send Service Reject
if (!nc or !uc or !nc->security_ctx or (decoded_size == KEncodeDecodeError)) { if (!nc or !uc or !nc->security_ctx.has_value() or
(decoded_size == KEncodeDecodeError)) {
// TODO: Try to get // TODO: Try to get
Logger::amf_n1().debug( Logger::amf_n1().debug(
"Cannot find NAS/UE context, send Service Reject to UE"); "Cannot find NAS/UE context, send Service Reject to UE");
...@@ -878,8 +887,8 @@ void amf_n1::service_request_handle( ...@@ -878,8 +887,8 @@ void amf_n1::service_request_handle(
// Otherwise, continue to process Service Request message // Otherwise, continue to process Service Request message
set_amf_ue_ngap_id_2_nas_context(amf_ue_ngap_id, nc); set_amf_ue_ngap_id_2_nas_context(amf_ue_ngap_id, nc);
nas_secu_ctx* secu = nc->security_ctx; // TODO: remove naked ptr
if (!secu) { if (!nc->security_ctx.has_value()) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return; return;
} }
...@@ -984,14 +993,23 @@ void amf_n1::service_request_handle( ...@@ -984,14 +993,23 @@ void amf_n1::service_request_handle(
int encoded_size = service_accept->Encode(buffer, BUFFER_SIZE_256); int encoded_size = service_accept->Encode(buffer, BUFFER_SIZE_256);
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK, nc->security_ctx.value(), false, INTEGRITY_PROTECTED_AND_CIPHERED,
buffer, encoded_size, protected_nas); NAS_MESSAGE_DOWNLINK, buffer, encoded_size, protected_nas);
uint8_t* kamf = nc->kamf[secu->vector_pointer];
uint8_t kgnb[32]; uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS];
uint32_t ulcount = secu->ul_count.seq_num | (secu->ul_count.overflow << 8); uint8_t kgnb[AUTH_VECTOR_LENGTH_OCTETS];
Logger::amf_n1().debug("uplink count(%d)", secu->ul_count.seq_num); if (!nc->get_kamf(nc->security_ctx.value().vector_pointer, kamf)) {
output_wrapper::print_buffer("amf_n1", "Kamf", kamf, 32); Logger::amf_n1().warn("No Kamf found");
Authentication_5gaka::derive_kgnb(ulcount, 0x01, kamf, kgnb); return;
}
uint32_t ulcount = nc->security_ctx.value().ul_count.seq_num |
(nc->security_ctx.value().ul_count.overflow << 8);
Logger::amf_n1().debug(
"uplink count(%d)", nc->security_ctx.value().ul_count.seq_num);
output_wrapper::print_buffer(
"amf_n1", "Kamf", kamf, AUTH_VECTOR_LENGTH_OCTETS);
Authentication_5gaka::derive_kgnb(
ulcount, 0x01, kamf, kgnb); // TODO: remove hardcoded value
std::shared_ptr<itti_initial_context_setup_request> itti_msg = std::shared_ptr<itti_initial_context_setup_request> itti_msg =
std::make_shared<itti_initial_context_setup_request>( std::make_shared<itti_initial_context_setup_request>(
...@@ -999,7 +1017,7 @@ void amf_n1::service_request_handle( ...@@ -999,7 +1017,7 @@ void amf_n1::service_request_handle(
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id; itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id; itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->nas = bstrcpy(protected_nas); itti_msg->nas = bstrcpy(protected_nas);
itti_msg->kgnb = blk2bstr(kgnb, 32); itti_msg->kgnb = blk2bstr(kgnb, AUTH_VECTOR_LENGTH_OCTETS);
itti_msg->is_sr = true; // Service Request indicator itti_msg->is_sr = true; // Service Request indicator
itti_msg->is_pdu_exist = false; itti_msg->is_pdu_exist = false;
...@@ -1033,14 +1051,23 @@ void amf_n1::service_request_handle( ...@@ -1033,14 +1051,23 @@ void amf_n1::service_request_handle(
int encoded_size = service_accept->Encode(buffer, BUFFER_SIZE_256); int encoded_size = service_accept->Encode(buffer, BUFFER_SIZE_256);
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK, nc->security_ctx.value(), false, INTEGRITY_PROTECTED_AND_CIPHERED,
buffer, encoded_size, protected_nas); NAS_MESSAGE_DOWNLINK, buffer, encoded_size, protected_nas);
uint8_t* kamf = nc->kamf[secu->vector_pointer];
uint8_t kgnb[32]; uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS];
uint32_t ulcount = secu->ul_count.seq_num | (secu->ul_count.overflow << 8); uint8_t kgnb[AUTH_VECTOR_LENGTH_OCTETS];
Logger::amf_n1().debug("uplink count(%d)", secu->ul_count.seq_num); if (!nc->get_kamf(nc->security_ctx.value().vector_pointer, kamf)) {
output_wrapper::print_buffer("amf_n1", "Kamf", kamf, 32); Logger::amf_n1().warn("No Kamf found");
Authentication_5gaka::derive_kgnb(ulcount, 0x01, kamf, kgnb); return;
}
uint32_t ulcount = nc->security_ctx.value().ul_count.seq_num |
(nc->security_ctx.value().ul_count.overflow << 8);
Logger::amf_n1().debug(
"uplink count(%d)", nc->security_ctx.value().ul_count.seq_num);
output_wrapper::print_buffer(
"amf_n1", "Kamf", kamf, AUTH_VECTOR_LENGTH_OCTETS);
Authentication_5gaka::derive_kgnb(
ulcount, 0x01, kamf, kgnb); // TODO: remove hardcoded value
std::shared_ptr<itti_initial_context_setup_request> itti_msg = std::shared_ptr<itti_initial_context_setup_request> itti_msg =
std::make_shared<itti_initial_context_setup_request>( std::make_shared<itti_initial_context_setup_request>(
...@@ -1048,7 +1075,7 @@ void amf_n1::service_request_handle( ...@@ -1048,7 +1075,7 @@ void amf_n1::service_request_handle(
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id; itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id; itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->nas = bstrcpy(protected_nas); itti_msg->nas = bstrcpy(protected_nas);
itti_msg->kgnb = blk2bstr(kgnb, 32); itti_msg->kgnb = blk2bstr(kgnb, AUTH_VECTOR_LENGTH_OCTETS);
itti_msg->is_sr = true; // Service Request indicator itti_msg->is_sr = true; // Service Request indicator
itti_msg->pdu_session_id = pdu_session_id; itti_msg->pdu_session_id = pdu_session_id;
itti_msg->is_pdu_exist = true; itti_msg->is_pdu_exist = true;
...@@ -1193,8 +1220,8 @@ void amf_n1::registration_request_handle( ...@@ -1193,8 +1220,8 @@ void amf_n1::registration_request_handle(
set_supi_2_ran_id(supi, ran_ue_ngap_id); set_supi_2_ran_id(supi, ran_ue_ngap_id);
nc->is_auth_vectors_present = false; nc->is_auth_vectors_present = false;
nc->is_current_security_available = false; nc->is_current_security_available = false;
if (nc->security_ctx) if (nc->security_ctx.has_value())
nc->security_ctx->sc_type = SECURITY_CTX_TYPE_NOT_AVAILABLE; nc->security_ctx.value().sc_type = SECURITY_CTX_TYPE_NOT_AVAILABLE;
} else { } else {
Logger::amf_n1().debug( Logger::amf_n1().debug(
"No existing nas_context with amf_ue_ngap_id (" AMF_UE_NGAP_ID_FMT "No existing nas_context with amf_ue_ngap_id (" AMF_UE_NGAP_ID_FMT
...@@ -1260,8 +1287,8 @@ void amf_n1::registration_request_handle( ...@@ -1260,8 +1287,8 @@ void amf_n1::registration_request_handle(
nc->is_auth_vectors_present = false; nc->is_auth_vectors_present = false;
nc->is_current_security_available = false; nc->is_current_security_available = false;
if (nc->security_ctx) if (nc->security_ctx.has_value())
nc->security_ctx->sc_type = SECURITY_CTX_TYPE_NOT_AVAILABLE; nc->security_ctx.value().sc_type = SECURITY_CTX_TYPE_NOT_AVAILABLE;
} else { } else {
Logger::amf_n1().error("No nas_context with GUTI (%s)", guti.c_str()); Logger::amf_n1().error("No nas_context with GUTI (%s)", guti.c_str());
send_registration_reject_msg( send_registration_reject_msg(
...@@ -1292,8 +1319,8 @@ void amf_n1::registration_request_handle( ...@@ -1292,8 +1319,8 @@ void amf_n1::registration_request_handle(
nc->amf_ue_ngap_id = amf_ue_ngap_id; nc->amf_ue_ngap_id = amf_ue_ngap_id;
nc->serving_network = snn; nc->serving_network = snn;
if (nc->security_ctx) if (nc->security_ctx.has_value())
nc->security_ctx->sc_type = SECURITY_CTX_TYPE_NOT_AVAILABLE; nc->security_ctx.value().sc_type = SECURITY_CTX_TYPE_NOT_AVAILABLE;
// Update UE context // Update UE context
if (uc != nullptr) { if (uc != nullptr) {
...@@ -1671,7 +1698,7 @@ void amf_n1::run_registration_procedure(std::shared_ptr<nas_context>& nc) { ...@@ -1671,7 +1698,7 @@ void amf_n1::run_registration_procedure(std::shared_ptr<nas_context>& nc) {
"Authentication vector in nas_context is not available"); "Authentication vector in nas_context is not available");
if (auth_vectors_generator(nc)) { // all authentication in one (AMF) if (auth_vectors_generator(nc)) { // all authentication in one (AMF)
ngksi_t ngksi = 0; ngksi_t ngksi = 0;
if (nc->security_ctx && if (nc->security_ctx.has_value() &&
nc->ngksi != NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE) { nc->ngksi != NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE) {
// ngksi = (nc->ngksi + 1) % (NGKSI_MAX_VALUE + 1); // ngksi = (nc->ngksi + 1) % (NGKSI_MAX_VALUE + 1);
ngksi = (nc->amf_ue_ngap_id + 1); // % (NGKSI_MAX_VALUE + 1); ngksi = (nc->amf_ue_ngap_id + 1); // % (NGKSI_MAX_VALUE + 1);
...@@ -1688,7 +1715,7 @@ void amf_n1::run_registration_procedure(std::shared_ptr<nas_context>& nc) { ...@@ -1688,7 +1715,7 @@ void amf_n1::run_registration_procedure(std::shared_ptr<nas_context>& nc) {
Logger::amf_n1().debug( Logger::amf_n1().debug(
"Authentication Vector in nas_context is available"); "Authentication Vector in nas_context is available");
ngksi_t ngksi = 0; ngksi_t ngksi = 0;
if (nc->security_ctx && if (nc->security_ctx.has_value() &&
nc->ngksi != NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE) { nc->ngksi != NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE) {
// ngksi = (nc->ngksi + 1) % (NGKSI_MAX_VALUE + 1); // ngksi = (nc->ngksi + 1) % (NGKSI_MAX_VALUE + 1);
ngksi = (nc->amf_ue_ngap_id + 1); // % (NGKSI_MAX_VALUE + 1); ngksi = (nc->amf_ue_ngap_id + 1); // % (NGKSI_MAX_VALUE + 1);
...@@ -1739,6 +1766,7 @@ bool amf_n1::auth_vectors_generator(std::shared_ptr<nas_context>& nc) { ...@@ -1739,6 +1766,7 @@ bool amf_n1::auth_vectors_generator(std::shared_ptr<nas_context>& nc) {
Authentication_5gaka::derive_kamf( Authentication_5gaka::derive_kamf(
nc->imsi, nc->_5g_av[i].kseaf, nc->kamf[i], nc->imsi, nc->_5g_av[i].kseaf, nc->kamf[i],
0x0000); // second parameter: abba 0x0000); // second parameter: abba
// TODO: remove hardcoded value
} }
} }
return true; return true;
...@@ -1882,9 +1910,10 @@ bool amf_n1::_5g_aka_confirmation_from_ausf( ...@@ -1882,9 +1910,10 @@ bool amf_n1::_5g_aka_confirmation_from_ausf(
if (!confirmationdataresponse.kseafIsSet()) return false; if (!confirmationdataresponse.kseafIsSet()) return false;
unsigned char* kseaf_hex = unsigned char* kseaf_hex =
conv::format_string_as_hex(confirmationdataresponse.getKseaf()); conv::format_string_as_hex(confirmationdataresponse.getKseaf());
memcpy(nc->_5g_av[0].kseaf, kseaf_hex, 32); memcpy(nc->_5g_av[0].kseaf, kseaf_hex, AUTH_VECTOR_LENGTH_OCTETS);
output_wrapper::print_buffer( output_wrapper::print_buffer(
"amf_n1", "5G AV: kseaf", nc->_5g_av[0].kseaf, 32); "amf_n1", "5G AV: kseaf", nc->_5g_av[0].kseaf,
AUTH_VECTOR_LENGTH_OCTETS);
free_wrapper((void**) &kseaf_hex); free_wrapper((void**) &kseaf_hex);
Logger::amf_n1().debug("Deriving Kamf"); Logger::amf_n1().debug("Deriving Kamf");
...@@ -1892,7 +1921,8 @@ bool amf_n1::_5g_aka_confirmation_from_ausf( ...@@ -1892,7 +1921,8 @@ bool amf_n1::_5g_aka_confirmation_from_ausf(
Authentication_5gaka::derive_kamf( Authentication_5gaka::derive_kamf(
nc->imsi, nc->_5g_av[i].kseaf, nc->kamf[i], nc->imsi, nc->_5g_av[i].kseaf, nc->kamf[i],
0x0000); // second parameter: abba 0x0000); // second parameter: abba
output_wrapper::print_buffer("amf_n1", "Kamf", nc->kamf[i], 32); output_wrapper::print_buffer(
"amf_n1", "Kamf", nc->kamf[i], AUTH_VECTOR_LENGTH_OCTETS);
} }
} catch (nlohmann::json::exception& e) { } catch (nlohmann::json::exception& e) {
Logger::amf_n1().info("Could not get JSON content from AUSF response"); Logger::amf_n1().info("Could not get JSON content from AUSF response");
...@@ -1917,15 +1947,16 @@ bool amf_n1::authentication_vectors_generator_in_ausf( ...@@ -1917,15 +1947,16 @@ bool amf_n1::authentication_vectors_generator_in_ausf(
memcpy(&inputString[i][0], rand[i], 16); memcpy(&inputString[i][0], rand[i], 16);
memcpy(&inputString[i][16], xresStar[i], 16); memcpy(&inputString[i][16], xresStar[i], 16);
unsigned char sha256Out[Sha256::DIGEST_SIZE]; unsigned char sha256Out[Sha256::DIGEST_SIZE];
sha256((unsigned char*) inputString[i], 32, sha256Out); sha256(
(unsigned char*) inputString[i], AUTH_VECTOR_LENGTH_OCTETS, sha256Out);
for (int j = 0; j < 16; j++) for (int j = 0; j < 16; j++)
nc->_5g_av[i].hxresStar[j] = (uint8_t) sha256Out[j]; nc->_5g_av[i].hxresStar[j] = (uint8_t) sha256Out[j];
memcpy(nc->_5g_av[i].rand, nc->_5g_he_av[i].rand, 16); memcpy(nc->_5g_av[i].rand, nc->_5g_he_av[i].rand, 16);
memcpy(nc->_5g_av[i].autn, nc->_5g_he_av[i].autn, 16); memcpy(nc->_5g_av[i].autn, nc->_5g_he_av[i].autn, 16);
uint8_t kseaf[32]; uint8_t kseaf[AUTH_VECTOR_LENGTH_OCTETS];
Authentication_5gaka::derive_kseaf( Authentication_5gaka::derive_kseaf(
nc->serving_network, nc->_5g_he_av[i].kausf, kseaf); nc->serving_network, nc->_5g_he_av[i].kausf, kseaf);
memcpy(nc->_5g_av[i].kseaf, kseaf, 32); memcpy(nc->_5g_av[i].kseaf, kseaf, AUTH_VECTOR_LENGTH_OCTETS);
} }
return true; return true;
} }
...@@ -2055,7 +2086,7 @@ void amf_n1::generate_5g_he_av_in_udm( ...@@ -2055,7 +2086,7 @@ void amf_n1::generate_5g_he_av_in_udm(
ck, ik, serving_network, sqn, ak, ck, ik, serving_network, sqn, ak,
vector.kausf); // derive Kausf vector.kausf); // derive Kausf
// output_wrapper::print_buffer("amf_n1", "Result For KDF: Kausf(5G HE AV)", // output_wrapper::print_buffer("amf_n1", "Result For KDF: Kausf(5G HE AV)",
// vector.kausf, 32); // vector.kausf, AUTH_VECTOR_LENGTH_OCTETS);
Logger::amf_n1().debug("Generate_5g_he_av_in_udm finished!"); Logger::amf_n1().debug("Generate_5g_he_av_in_udm finished!");
return; return;
} }
...@@ -2093,14 +2124,16 @@ void amf_n1::annex_a_4_33501( ...@@ -2093,14 +2124,16 @@ void amf_n1::annex_a_4_33501(
oldS[33] = 0x08; oldS[33] = 0x08;
output_wrapper::print_buffer( output_wrapper::print_buffer(
"amf_n1", "Input string: ", S, 31 + netName.size); "amf_n1", "Input string: ", S, 31 + netName.size);
uint8_t key[32]; uint8_t key[AUTH_VECTOR_LENGTH_OCTETS];
memcpy(&key[0], ck, 16); memcpy(&key[0], ck, 16);
memcpy(&key[16], ik, 16); // KEY memcpy(&key[16], ik, 16); // KEY
// Authentication_5gaka::kdf(key, 32, oldS, 33, output, 16); // Authentication_5gaka::kdf(key, AUTH_VECTOR_LENGTH_OCTETS, oldS, 33, output,
uint8_t out[32]; // 16);
uint8_t out[AUTH_VECTOR_LENGTH_OCTETS];
Authentication_5gaka::kdf(key, 32, S, 31 + netName.size, out, 32); Authentication_5gaka::kdf(key, 32, S, 31 + netName.size, out, 32);
for (int i = 0; i < 16; i++) output[i] = out[16 + i]; for (int i = 0; i < 16; i++) output[i] = out[16 + i];
output_wrapper::print_buffer("amf_n1", "XRES*(new)", out, 32); output_wrapper::print_buffer(
"amf_n1", "XRES*(new)", out, AUTH_VECTOR_LENGTH_OCTETS);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -2110,15 +2143,16 @@ void amf_n1::handle_auth_vector_successful_result( ...@@ -2110,15 +2143,16 @@ void amf_n1::handle_auth_vector_successful_result(
"Received Security Vectors, try to setup security with the UE"); "Received Security Vectors, try to setup security with the UE");
nc->is_auth_vectors_present = true; nc->is_auth_vectors_present = true;
ngksi_t ngksi = 0; ngksi_t ngksi = 0;
if (!nc->security_ctx) { if (!nc->security_ctx.has_value()) {
nc->security_ctx = new nas_secu_ctx(); nc->security_ctx = std::make_optional<nas_secu_ctx>();
nc->security_ctx->sc_type = SECURITY_CTX_TYPE_NOT_AVAILABLE; nc->security_ctx.value().sc_type = SECURITY_CTX_TYPE_NOT_AVAILABLE;
if (nc->security_ctx && nc->ngksi != NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE) if (nc->security_ctx.has_value() &&
nc->ngksi != NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE)
ngksi = (nc->amf_ue_ngap_id + 1) % (NGKSI_MAX_VALUE + 1); ngksi = (nc->amf_ue_ngap_id + 1) % (NGKSI_MAX_VALUE + 1);
// ensure which vector is available? // ensure which vector is available?
nc->ngksi = ngksi; nc->ngksi = ngksi;
} }
int vindex = nc->security_ctx->vector_pointer; int vindex = nc->security_ctx.value().vector_pointer;
if (!start_authentication_procedure(nc, vindex, nc->ngksi)) { if (!start_authentication_procedure(nc, vindex, nc->ngksi)) {
Logger::amf_n1().error("Start Authentication Procedure Failure, reject..."); Logger::amf_n1().error("Start Authentication Procedure Failure, reject...");
Logger::amf_n1().error( Logger::amf_n1().error(
...@@ -2239,7 +2273,8 @@ void amf_n1::authentication_response_handle( ...@@ -2239,7 +2273,8 @@ void amf_n1::authentication_response_handle(
} else { } else {
// Get stored XRES* // Get stored XRES*
int secu_index = 0; int secu_index = 0;
if (nc->security_ctx) secu_index = nc->security_ctx->vector_pointer; if (nc->security_ctx.has_value())
secu_index = nc->security_ctx.value().vector_pointer;
uint8_t* hxresStar = nc->_5g_av[secu_index].hxresStar; uint8_t* hxresStar = nc->_5g_av[secu_index].hxresStar;
// Calculate HRES* from received RES*, then compare with XRES stored in // Calculate HRES* from received RES*, then compare with XRES stored in
...@@ -2354,7 +2389,13 @@ void amf_n1::authentication_failure_handle( ...@@ -2354,7 +2389,13 @@ void amf_n1::authentication_failure_handle(
ngksi_t ngksi = ngksi_t ngksi =
(nc->ngksi + 1) % (NGKSI_MAX_VALUE + 1); // To be verified (nc->ngksi + 1) % (NGKSI_MAX_VALUE + 1); // To be verified
nc->ngksi = ngksi; nc->ngksi = ngksi;
int vindex = nc->security_ctx->vector_pointer;
if (!nc->security_ctx.has_value()) {
Logger::amf_n2().error("No Security Context found");
// TODO:
return;
}
int vindex = nc->security_ctx.value().vector_pointer;
if (!start_authentication_procedure(nc, vindex, nc->ngksi)) { if (!start_authentication_procedure(nc, vindex, nc->ngksi)) {
Logger::amf_n1().error( Logger::amf_n1().error(
"Start Authentication procedure failure, reject..."); "Start Authentication procedure failure, reject...");
...@@ -2380,34 +2421,36 @@ bool amf_n1::start_security_mode_control_procedure( ...@@ -2380,34 +2421,36 @@ bool amf_n1::start_security_mode_control_procedure(
uint8_t amf_nea = EA0_5G; uint8_t amf_nea = EA0_5G;
uint8_t amf_nia = IA0_5G; uint8_t amf_nia = IA0_5G;
// Decide which ea/ia alg used by UE, which is supported by network // Decide which ea/ia alg used by UE, which is supported by network
nas_secu_ctx* secu_ctx = nc->security_ctx;
if (!secu_ctx) { if (!nc->security_ctx.has_value()) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return false; return false;
} }
if (secu_ctx->sc_type == SECURITY_CTX_TYPE_NOT_AVAILABLE && if (nc->security_ctx.value().sc_type == SECURITY_CTX_TYPE_NOT_AVAILABLE &&
nc->is_common_procedure_for_security_mode_control_running) { nc->is_common_procedure_for_security_mode_control_running) {
Logger::amf_n1().debug( Logger::amf_n1().debug(
"Using INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX for SecurityModeControl " "Using INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX for SecurityModeControl "
"message"); "message");
secu_ctx->ngksi = nc->ngksi; nc->security_ctx.value().ngksi = nc->ngksi;
secu_ctx->dl_count.overflow = 0; nc->security_ctx.value().dl_count.overflow = 0;
secu_ctx->dl_count.seq_num = 0; nc->security_ctx.value().dl_count.seq_num = 0;
secu_ctx->ul_count.overflow = 0; nc->security_ctx.value().ul_count.overflow = 0;
secu_ctx->ul_count.seq_num = 0; nc->security_ctx.value().ul_count.seq_num = 0;
security_select_algorithms( security_select_algorithms(
nc->ue_security_capability.GetEa(), nc->ue_security_capability.GetIa(), nc->ue_security_capability.GetEa(), nc->ue_security_capability.GetIa(),
amf_nea, amf_nia); amf_nea, amf_nia);
secu_ctx->nas_algs.integrity = amf_nia; nc->security_ctx.value().nas_algs.integrity = amf_nia;
secu_ctx->nas_algs.encryption = amf_nea; nc->security_ctx.value().nas_algs.encryption = amf_nea;
secu_ctx->sc_type = SECURITY_CTX_TYPE_FULL_NATIVE; nc->security_ctx.value().sc_type = SECURITY_CTX_TYPE_FULL_NATIVE;
Authentication_5gaka::derive_knas( Authentication_5gaka::derive_knas(
NAS_INT_ALG, secu_ctx->nas_algs.integrity, NAS_INT_ALG, nc->security_ctx.value().nas_algs.integrity,
nc->kamf[secu_ctx->vector_pointer], secu_ctx->knas_int); nc->kamf[nc->security_ctx.value().vector_pointer],
nc->security_ctx.value().knas_int);
Authentication_5gaka::derive_knas( Authentication_5gaka::derive_knas(
NAS_ENC_ALG, secu_ctx->nas_algs.encryption, NAS_ENC_ALG, nc->security_ctx.value().nas_algs.encryption,
nc->kamf[secu_ctx->vector_pointer], secu_ctx->knas_enc); nc->kamf[nc->security_ctx.value().vector_pointer],
nc->security_ctx.value().knas_enc);
security_context_is_new = true; security_context_is_new = true;
nc->is_current_security_available = true; nc->is_current_security_available = true;
} }
...@@ -2431,8 +2474,9 @@ bool amf_n1::start_security_mode_control_procedure( ...@@ -2431,8 +2474,9 @@ bool amf_n1::start_security_mode_control_procedure(
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu_ctx, security_context_is_new, INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX, nc->security_ctx.value(), security_context_is_new,
NAS_MESSAGE_DOWNLINK, buffer, encoded_size, protected_nas); INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX, NAS_MESSAGE_DOWNLINK, buffer,
encoded_size, protected_nas);
output_wrapper::print_buffer( output_wrapper::print_buffer(
"amf_n1", "Encrypted Security-Mode-Command message buffer", "amf_n1", "Encrypted Security-Mode-Command message buffer",
(uint8_t*) bdata(protected_nas), blength(protected_nas)); (uint8_t*) bdata(protected_nas), blength(protected_nas));
...@@ -2652,16 +2696,16 @@ void amf_n1::security_mode_complete_handle( ...@@ -2652,16 +2696,16 @@ void amf_n1::security_mode_complete_handle(
set_guti_2_nas_context(guti, nc); set_guti_2_nas_context(guti, nc);
nc->is_common_procedure_for_security_mode_control_running = false; nc->is_common_procedure_for_security_mode_control_running = false;
nas_secu_ctx* secu = nc->security_ctx;
if (!secu) { if (!nc->security_ctx.has_value()) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return; return;
} }
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK, nc->security_ctx.value(), false, INTEGRITY_PROTECTED_AND_CIPHERED,
buffer, encoded_size, protected_nas); NAS_MESSAGE_DOWNLINK, buffer, encoded_size, protected_nas);
if (!uc->is_ue_context_request) { if (!uc->is_ue_context_request) {
Logger::amf_n1().debug( Logger::amf_n1().debug(
...@@ -2691,20 +2735,25 @@ void amf_n1::security_mode_complete_handle( ...@@ -2691,20 +2735,25 @@ void amf_n1::security_mode_complete_handle(
} else { } else {
// use InitialContextSetupRequest (NGAP message) to convey Registration // use InitialContextSetupRequest (NGAP message) to convey Registration
// Accept // Accept
uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS];
uint8_t* kamf = nc->kamf[secu->vector_pointer]; uint8_t kgnb[AUTH_VECTOR_LENGTH_OCTETS];
uint8_t kgnb[32]; if (!nc->get_kamf(nc->security_ctx.value().vector_pointer, kamf)) {
uint32_t ulcount = secu->ul_count.seq_num | (secu->ul_count.overflow << 8); Logger::amf_n1().warn("No Kamf found");
Authentication_5gaka::derive_kgnb(0, 0x01, kamf, kgnb); return;
output_wrapper::print_buffer("amf_n1", "Kamf", kamf, 32); }
// Authentication_5gaka::derive_kgnb(ulcount, 0x01, kamf, kgnb); uint32_t ulcount = nc->security_ctx.value().ul_count.seq_num |
(nc->security_ctx.value().ul_count.overflow << 8);
Authentication_5gaka::derive_kgnb(
0, 0x01, kamf, kgnb); // TODO: remove harcoded value
output_wrapper::print_buffer(
"amf_n1", "Kamf", kamf, AUTH_VECTOR_LENGTH_OCTETS);
std::shared_ptr<itti_initial_context_setup_request> itti_msg = std::shared_ptr<itti_initial_context_setup_request> itti_msg =
std::make_shared<itti_initial_context_setup_request>( std::make_shared<itti_initial_context_setup_request>(
TASK_AMF_N1, TASK_AMF_N2); TASK_AMF_N1, TASK_AMF_N2);
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id; itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id; itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->kgnb = blk2bstr(kgnb, 32); itti_msg->kgnb = blk2bstr(kgnb, AUTH_VECTOR_LENGTH_OCTETS);
itti_msg->nas = protected_nas; itti_msg->nas = protected_nas;
itti_msg->is_pdu_exist = false; // no pdu context itti_msg->is_pdu_exist = false; // no pdu context
itti_msg->is_sr = false; // TODO: for Service Request procedure itti_msg->is_sr = false; // TODO: for Service Request procedure
...@@ -2746,8 +2795,7 @@ void amf_n1::registration_complete_handle( ...@@ -2746,8 +2795,7 @@ void amf_n1::registration_complete_handle(
return; return;
} }
nas_secu_ctx* secu = nc->security_ctx; if (!nc->security_ctx.has_value()) {
if (!secu) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return; return;
} }
...@@ -2792,8 +2840,8 @@ void amf_n1::registration_complete_handle( ...@@ -2792,8 +2840,8 @@ void amf_n1::registration_complete_handle(
// Protect NAS message // Protect NAS message
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK, security_ctx.value(), false, INTEGRITY_PROTECTED_AND_CIPHERED,
buffer, encoded_size, protected_nas); NAS_MESSAGE_DOWNLINK, buffer, encoded_size, protected_nas);
std::shared_ptr<itti_dl_nas_transport> dnt = std::shared_ptr<itti_dl_nas_transport> dnt =
std::make_shared<itti_dl_nas_transport>(TASK_AMF_N1, TASK_AMF_N2); std::make_shared<itti_dl_nas_transport>(TASK_AMF_N1, TASK_AMF_N2);
...@@ -2812,7 +2860,7 @@ void amf_n1::registration_complete_handle( ...@@ -2812,7 +2860,7 @@ void amf_n1::registration_complete_handle(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void amf_n1::encode_nas_message_protected( void amf_n1::encode_nas_message_protected(
nas_secu_ctx* nsc, bool is_secu_ctx_new, uint8_t security_header_type, nas_secu_ctx& nsc, bool is_secu_ctx_new, uint8_t security_header_type,
uint8_t direction, uint8_t* input_nas_buf, int input_nas_len, uint8_t direction, uint8_t* input_nas_buf, int input_nas_len,
bstring& protected_nas) { bstring& protected_nas) {
Logger::amf_n1().debug("Encoding nas_message_protected..."); Logger::amf_n1().debug("Encoding nas_message_protected...");
...@@ -2830,7 +2878,7 @@ void amf_n1::encode_nas_message_protected( ...@@ -2830,7 +2878,7 @@ void amf_n1::encode_nas_message_protected(
nas_message_cipher_protected(nsc, NAS_MESSAGE_DOWNLINK, input, ciphered); nas_message_cipher_protected(nsc, NAS_MESSAGE_DOWNLINK, input, ciphered);
protected_nas_buf[0] = EPD_5GS_MM_MSG; protected_nas_buf[0] = EPD_5GS_MM_MSG;
protected_nas_buf[1] = INTEGRITY_PROTECTED_AND_CIPHERED; protected_nas_buf[1] = INTEGRITY_PROTECTED_AND_CIPHERED;
protected_nas_buf[6] = (uint8_t) nsc->dl_count.seq_num; protected_nas_buf[6] = (uint8_t) nsc.dl_count.seq_num;
uint8_t* buf_tmp = (uint8_t*) bdata(ciphered); uint8_t* buf_tmp = (uint8_t*) bdata(ciphered);
if (buf_tmp != nullptr) if (buf_tmp != nullptr)
...@@ -2852,13 +2900,13 @@ void amf_n1::encode_nas_message_protected( ...@@ -2852,13 +2900,13 @@ void amf_n1::encode_nas_message_protected(
} break; } break;
case INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX: { case INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX: {
if ((nsc == nullptr) || !is_secu_ctx_new) { if (!is_secu_ctx_new) {
Logger::amf_n1().error("Security context is too old"); Logger::amf_n1().error("Security context is too old");
return; return;
} }
protected_nas_buf[0] = EPD_5GS_MM_MSG; protected_nas_buf[0] = EPD_5GS_MM_MSG;
protected_nas_buf[1] = INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX; protected_nas_buf[1] = INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX;
protected_nas_buf[6] = (uint8_t) nsc->dl_count.seq_num; protected_nas_buf[6] = (uint8_t) nsc.dl_count.seq_num;
memcpy(&protected_nas_buf[7], input_nas_buf, input_nas_len); memcpy(&protected_nas_buf[7], input_nas_buf, input_nas_len);
uint32_t mac32 = {}; uint32_t mac32 = {};
if (!(nas_message_integrity_protected( if (!(nas_message_integrity_protected(
...@@ -2877,34 +2925,33 @@ void amf_n1::encode_nas_message_protected( ...@@ -2877,34 +2925,33 @@ void amf_n1::encode_nas_message_protected(
} break; } break;
} }
protected_nas = blk2bstr(protected_nas_buf, encoded_size); protected_nas = blk2bstr(protected_nas_buf, encoded_size);
nsc->dl_count.seq_num++; nsc.dl_count.seq_num++;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool amf_n1::nas_message_integrity_protected( bool amf_n1::nas_message_integrity_protected(
nas_secu_ctx* nsc, uint8_t direction, uint8_t* input_nas, int input_nas_len, nas_secu_ctx& nsc, uint8_t direction, uint8_t* input_nas, int input_nas_len,
uint32_t& mac32) { uint32_t& mac32) {
if (nsc == nullptr) return false;
uint32_t count = 0x00000000; uint32_t count = 0x00000000;
if (direction) { if (direction) {
count = 0x00000000 | ((nsc->dl_count.overflow & 0x0000ffff) << 8) | count = 0x00000000 | ((nsc.dl_count.overflow & 0x0000ffff) << 8) |
((nsc->dl_count.seq_num & 0x000000ff)); ((nsc.dl_count.seq_num & 0x000000ff));
} else { } else {
count = 0x00000000 | ((nsc->ul_count.overflow & 0x0000ffff) << 8) | count = 0x00000000 | ((nsc.ul_count.overflow & 0x0000ffff) << 8) |
((nsc->ul_count.seq_num & 0x000000ff)); ((nsc.ul_count.seq_num & 0x000000ff));
} }
nas_stream_cipher_t stream_cipher = {0}; nas_stream_cipher_t stream_cipher = {0};
uint8_t mac[4]; uint8_t mac[4];
stream_cipher.key = nsc->knas_int; stream_cipher.key = nsc.knas_int;
output_wrapper::print_buffer( output_wrapper::print_buffer(
"amf_n1", "Parameters for NIA: Knas_int", nsc->knas_int, "amf_n1", "Parameters for NIA: Knas_int", nsc.knas_int,
AUTH_KNAS_INT_SIZE); AUTH_KNAS_INT_SIZE);
stream_cipher.key_length = AUTH_KNAS_INT_SIZE; stream_cipher.key_length = AUTH_KNAS_INT_SIZE;
stream_cipher.count = *(input_nas); stream_cipher.count = *(input_nas);
// stream_cipher.count = count; // stream_cipher.count = count;
if (!direction) { if (!direction) {
nsc->ul_count.seq_num = stream_cipher.count; nsc.ul_count.seq_num = stream_cipher.count;
Logger::amf_n1().debug("Uplink count in uplink: %d", nsc->ul_count.seq_num); Logger::amf_n1().debug("Uplink count in uplink: %d", nsc.ul_count.seq_num);
} }
Logger::amf_n1().debug("Parameters for NIA, count: 0x%x", count); Logger::amf_n1().debug("Parameters for NIA, count: 0x%x", count);
stream_cipher.bearer = 0x01; // 33.501 section 8.1.1 stream_cipher.bearer = 0x01; // 33.501 section 8.1.1
...@@ -2917,7 +2964,7 @@ bool amf_n1::nas_message_integrity_protected( ...@@ -2917,7 +2964,7 @@ bool amf_n1::nas_message_integrity_protected(
"amf_n1", "Parameters for NIA, message: ", input_nas, input_nas_len); "amf_n1", "Parameters for NIA, message: ", input_nas, input_nas_len);
stream_cipher.blength = input_nas_len * 8; stream_cipher.blength = input_nas_len * 8;
switch (nsc->nas_algs.integrity & 0x0f) { switch (nsc.nas_algs.integrity & 0x0f) {
case IA0_5G: { case IA0_5G: {
Logger::amf_n1().debug("Integrity with algorithms: 5G-IA0"); Logger::amf_n1().debug("Integrity with algorithms: 5G-IA0");
return false; // plain msg return false; // plain msg
...@@ -2946,22 +2993,22 @@ bool amf_n1::nas_message_integrity_protected( ...@@ -2946,22 +2993,22 @@ bool amf_n1::nas_message_integrity_protected(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool amf_n1::nas_message_cipher_protected( bool amf_n1::nas_message_cipher_protected(
nas_secu_ctx* nsc, uint8_t direction, bstring input_nas, nas_secu_ctx& nsc, uint8_t direction, bstring input_nas,
bstring& output_nas) { bstring& output_nas) {
uint8_t* buf = (uint8_t*) bdata(input_nas); uint8_t* buf = (uint8_t*) bdata(input_nas);
int buf_len = blength(input_nas); int buf_len = blength(input_nas);
uint32_t count = 0x00000000; uint32_t count = 0x00000000;
if (direction) { if (direction) {
count = 0x00000000 | ((nsc->dl_count.overflow & 0x0000ffff) << 8) | count = 0x00000000 | ((nsc.dl_count.overflow & 0x0000ffff) << 8) |
((nsc->dl_count.seq_num & 0x000000ff)); ((nsc.dl_count.seq_num & 0x000000ff));
} else { } else {
Logger::amf_n1().debug("nsc->ul_count.overflow %x", nsc->ul_count.overflow); Logger::amf_n1().debug("nsc.ul_count.overflow %x", nsc.ul_count.overflow);
count = 0x00000000 | ((nsc->ul_count.overflow & 0x0000ffff) << 8) | count = 0x00000000 | ((nsc.ul_count.overflow & 0x0000ffff) << 8) |
((nsc->ul_count.seq_num & 0x000000ff)); ((nsc.ul_count.seq_num & 0x000000ff));
} }
nas_stream_cipher_t stream_cipher = {0}; nas_stream_cipher_t stream_cipher = {0};
uint8_t mac[4]; uint8_t mac[4];
stream_cipher.key = nsc->knas_enc; stream_cipher.key = nsc.knas_enc;
stream_cipher.key_length = AUTH_KNAS_ENC_SIZE; stream_cipher.key_length = AUTH_KNAS_ENC_SIZE;
stream_cipher.count = count; stream_cipher.count = count;
stream_cipher.bearer = 0x01; // 33.501 section 8.1.1 stream_cipher.bearer = 0x01; // 33.501 section 8.1.1
...@@ -2969,7 +3016,7 @@ bool amf_n1::nas_message_cipher_protected( ...@@ -2969,7 +3016,7 @@ bool amf_n1::nas_message_cipher_protected(
stream_cipher.message = (uint8_t*) bdata(input_nas); stream_cipher.message = (uint8_t*) bdata(input_nas);
stream_cipher.blength = blength(input_nas) << 3; stream_cipher.blength = blength(input_nas) << 3;
switch (nsc->nas_algs.encryption & 0x0f) { switch (nsc.nas_algs.encryption & 0x0f) {
case EA0_5G: { case EA0_5G: {
Logger::amf_n1().debug("Cipher protected with EA0_5G"); Logger::amf_n1().debug("Cipher protected with EA0_5G");
output_nas = blk2bstr(buf, buf_len); output_nas = blk2bstr(buf, buf_len);
...@@ -3384,8 +3431,7 @@ void amf_n1::run_mobility_registration_update_procedure( ...@@ -3384,8 +3431,7 @@ void amf_n1::run_mobility_registration_update_procedure(
return; return;
} }
nas_secu_ctx* secu = nc->security_ctx; if (!nc->security_ctx.has_value()) {
if (!secu) {
Logger::amf_n1().warn("No Security Context found"); Logger::amf_n1().warn("No Security Context found");
// Run Registration procedure // Run Registration procedure
// run_registration_procedure(nc); // run_registration_procedure(nc);
...@@ -3414,8 +3460,8 @@ void amf_n1::run_mobility_registration_update_procedure( ...@@ -3414,8 +3460,8 @@ void amf_n1::run_mobility_registration_update_procedure(
// protect nas message // protect nas message
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK, nc->security_ctx.value(), false, INTEGRITY_PROTECTED_AND_CIPHERED,
buffer, encoded_size, protected_nas); NAS_MESSAGE_DOWNLINK, buffer, encoded_size, protected_nas);
// get PDU session status // get PDU session status
std::vector<uint8_t> pdu_session_to_be_activated = {}; std::vector<uint8_t> pdu_session_to_be_activated = {};
...@@ -3428,23 +3474,25 @@ void amf_n1::run_mobility_registration_update_procedure( ...@@ -3428,23 +3474,25 @@ void amf_n1::run_mobility_registration_update_procedure(
uc->find_pdu_session_context(pdu_session_to_be_activated[0], psc); uc->find_pdu_session_context(pdu_session_to_be_activated[0], psc);
} }
uint8_t* kamf = nc->kamf[secu->vector_pointer]; uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS];
if (!kamf) { uint8_t kgnb[AUTH_VECTOR_LENGTH_OCTETS];
Logger::amf_n1().error("No Kamf found"); if (!nc->get_kamf(nc->security_ctx.value().vector_pointer, kamf)) {
Logger::amf_n1().warn("No Kamf found");
return; return;
} }
uint32_t ulcount = nc->security_ctx.value().ul_count.seq_num |
uint8_t kgnb[32]; (nc->security_ctx.value().ul_count.overflow << 8);
uint32_t ulcount = secu->ul_count.seq_num | (secu->ul_count.overflow << 8); Authentication_5gaka::derive_kgnb(
Authentication_5gaka::derive_kgnb(ulcount, 0x01, kamf, kgnb); ulcount, 0x01, kamf, kgnb); // TODO: remove hardcoded value
output_wrapper::print_buffer("amf_n1", "Kamf", kamf, 32); output_wrapper::print_buffer(
"amf_n1", "Kamf", kamf, AUTH_VECTOR_LENGTH_OCTETS);
std::shared_ptr<itti_initial_context_setup_request> itti_msg = std::shared_ptr<itti_initial_context_setup_request> itti_msg =
std::make_shared<itti_initial_context_setup_request>( std::make_shared<itti_initial_context_setup_request>(
TASK_AMF_N1, TASK_AMF_N2); TASK_AMF_N1, TASK_AMF_N2);
itti_msg->ran_ue_ngap_id = nc->ran_ue_ngap_id; itti_msg->ran_ue_ngap_id = nc->ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = nc->amf_ue_ngap_id; itti_msg->amf_ue_ngap_id = nc->amf_ue_ngap_id;
itti_msg->kgnb = blk2bstr(kgnb, 32); itti_msg->kgnb = blk2bstr(kgnb, AUTH_VECTOR_LENGTH_OCTETS);
itti_msg->nas = protected_nas; itti_msg->nas = protected_nas;
itti_msg->is_sr = true; // service request indicator, to be verified itti_msg->is_sr = true; // service request indicator, to be verified
...@@ -3497,16 +3545,15 @@ void amf_n1::run_periodic_registration_update_procedure( ...@@ -3497,16 +3545,15 @@ void amf_n1::run_periodic_registration_update_procedure(
return; return;
} }
nas_secu_ctx* secu = nc->security_ctx; if (!nc->security_ctx.has_value()) {
if (!secu) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return; return;
} }
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK, nc->security_ctx.value(), false, INTEGRITY_PROTECTED_AND_CIPHERED,
buffer, encoded_size, protected_nas); NAS_MESSAGE_DOWNLINK, buffer, encoded_size, protected_nas);
std::shared_ptr<itti_dl_nas_transport> itti_msg = std::shared_ptr<itti_dl_nas_transport> itti_msg =
std::make_shared<itti_dl_nas_transport>(TASK_AMF_N1, TASK_AMF_N2); std::make_shared<itti_dl_nas_transport>(TASK_AMF_N1, TASK_AMF_N2);
...@@ -3566,16 +3613,15 @@ void amf_n1::run_periodic_registration_update_procedure( ...@@ -3566,16 +3613,15 @@ void amf_n1::run_periodic_registration_update_procedure(
return; return;
} }
nas_secu_ctx* secu = nc->security_ctx; if (!nc->security_ctx.has_value()) {
if (!secu) {
Logger::amf_n1().error("No Security Context found"); Logger::amf_n1().error("No Security Context found");
return; return;
} }
bstring protected_nas = nullptr; bstring protected_nas = nullptr;
encode_nas_message_protected( encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK, nc->security_ctx.value(), false, INTEGRITY_PROTECTED_AND_CIPHERED,
buffer, encoded_size, protected_nas); NAS_MESSAGE_DOWNLINK, buffer, encoded_size, protected_nas);
std::shared_ptr<itti_dl_nas_transport> itti_msg = std::shared_ptr<itti_dl_nas_transport> itti_msg =
std::make_shared<itti_dl_nas_transport>(TASK_AMF_N1, TASK_AMF_N2); std::make_shared<itti_dl_nas_transport>(TASK_AMF_N1, TASK_AMF_N2);
......
...@@ -366,7 +366,7 @@ class amf_n1 { ...@@ -366,7 +366,7 @@ class amf_n1 {
/* /*
* Encode the NAS message with corresponding integrity and ciphered algorithms * Encode the NAS message with corresponding integrity and ciphered algorithms
* @param [nas_secu_ctx*] nsc: NAS Security context * @param [nas_secu_ctx&] nsc: NAS Security context
* @param [bool] is_secu_ctx_new: indicate the status of the security context * @param [bool] is_secu_ctx_new: indicate the status of the security context
* (new/old) * (new/old)
* @param [uint8_t] security_header_type: Security Header Type * @param [uint8_t] security_header_type: Security Header Type
...@@ -377,13 +377,13 @@ class amf_n1 { ...@@ -377,13 +377,13 @@ class amf_n1 {
* @return void * @return void
*/ */
void encode_nas_message_protected( void encode_nas_message_protected(
nas_secu_ctx* nsc, bool is_secu_ctx_new, uint8_t security_header_type, nas_secu_ctx& nsc, bool is_secu_ctx_new, uint8_t security_header_type,
uint8_t direction, uint8_t* input_nas_buf, int input_nas_len, uint8_t direction, uint8_t* input_nas_buf, int input_nas_len,
bstring& encrypted_nas); bstring& encrypted_nas);
/* /*
* Encrypt with integrity algorithm * Encrypt with integrity algorithm
* @param [nas_secu_ctx*] nsc: NAS Security context * @param [nas_secu_ctx&] nsc: NAS Security context
* @param [uint8_t] direction: Direction * @param [uint8_t] direction: Direction
* @param [uint8_t*] input_nas_buf: Buffer of the input NAS * @param [uint8_t*] input_nas_buf: Buffer of the input NAS
* @param [int] input_nas_les: Length of the buffer * @param [int] input_nas_les: Length of the buffer
...@@ -391,19 +391,19 @@ class amf_n1 { ...@@ -391,19 +391,19 @@ class amf_n1 {
* @return true if MAC can be calculated successfully, otherwise return false * @return true if MAC can be calculated successfully, otherwise return false
*/ */
bool nas_message_integrity_protected( bool nas_message_integrity_protected(
nas_secu_ctx* nsc, uint8_t direction, uint8_t* input_nas, nas_secu_ctx& nsc, uint8_t direction, uint8_t* input_nas,
int input_nas_len, uint32_t& mac); int input_nas_len, uint32_t& mac);
/* /*
* Cipher NAS message with the corresponding ciphered algorithm * Cipher NAS message with the corresponding ciphered algorithm
* @param [nas_secu_ctx*] nsc: NAS Security context * @param [nas_secu_ctx&] nsc: NAS Security context
* @param [uint8_t] direction: Direction * @param [uint8_t] direction: Direction
* @param [bstring] input_nas: Input NAS message * @param [bstring] input_nas: Input NAS message
* @param [bstring&] output_nas: Output NAS message * @param [bstring&] output_nas: Output NAS message
* @return true if message is successfully ciphered, otherwise return false * @return true if message is successfully ciphered, otherwise return false
*/ */
bool nas_message_cipher_protected( bool nas_message_cipher_protected(
nas_secu_ctx* nsc, uint8_t direction, bstring input_nas, nas_secu_ctx& nsc, uint8_t direction, bstring input_nas,
bstring& output_nas); bstring& output_nas);
// NOTE: All the MySQL-related functions are currently implemented in // NOTE: All the MySQL-related functions are currently implemented in
......
...@@ -1581,20 +1581,27 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) { ...@@ -1581,20 +1581,27 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
return false; return false;
} }
nas_secu_ctx* secu = nc->security_ctx; if (!nc->security_ctx.has_value()) {
if (!secu) {
Logger::amf_n2().error("No Security Context found"); Logger::amf_n2().error("No Security Context found");
return false; return false;
} }
uint8_t* kamf = nc->kamf[secu->vector_pointer];
uint8_t kgnb[32]; uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS];
uint32_t ulcount = secu->ul_count.seq_num | (secu->ul_count.overflow << 8); uint8_t kgnb[AUTH_VECTOR_LENGTH_OCTETS];
if (!nc->get_kamf(nc->security_ctx.value().vector_pointer, kamf)) {
Logger::amf_n1().warn("No Kamf found");
return false;
}
uint32_t ulcount = nc->security_ctx.value().ul_count.seq_num |
(nc->security_ctx.value().ul_count.overflow << 8);
Logger::amf_n2().debug( Logger::amf_n2().debug(
"Handover Required, Uplink count (%d)", secu->ul_count.seq_num); "Handover Required, Uplink count (%d)",
uint8_t knh[32]; nc->security_ctx.value().ul_count.seq_num);
uint8_t knh[AUTH_VECTOR_LENGTH_OCTETS];
Authentication_5gaka::handover_ncc_derive_knh( Authentication_5gaka::handover_ncc_derive_knh(
ulcount, 0x01, kamf, kgnb, knh, unc->ncc); ulcount, 0x01, kamf, kgnb, knh,
bstring knh_bs = blk2bstr(knh, 32); unc->ncc); // TODO: remove hardcoded value
bstring knh_bs = blk2bstr(knh, AUTH_VECTOR_LENGTH_OCTETS);
handover_request->setSecurityContext(unc->ncc /*NCC count*/, knh_bs); handover_request->setSecurityContext(unc->ncc /*NCC count*/, knh_bs);
string supi = conv::imsi_to_supi(nc->imsi); string supi = conv::imsi_to_supi(nc->imsi);
......
...@@ -203,7 +203,6 @@ void nf_profile::to_json(nlohmann::json& data) const { ...@@ -203,7 +203,6 @@ void nf_profile::to_json(nlohmann::json& data) const {
nlohmann::json tmp = {}; nlohmann::json tmp = {};
tmp["sst"] = s.sST; tmp["sst"] = s.sST;
tmp["sd"] = s.sD; tmp["sd"] = s.sD;
;
data["sNssais"].push_back(tmp); data["sNssais"].push_back(tmp);
} }
// ipv4_addresses // ipv4_addresses
......
...@@ -22,9 +22,7 @@ ...@@ -22,9 +22,7 @@
#include "nas_context.hpp" #include "nas_context.hpp"
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
nas_context::nas_context() nas_context::nas_context() : _5g_he_av(), _5g_av(), kamf(), _5gmm_capability() {
: _vector(), _5g_he_av(), _5g_av(), kamf(), _5gmm_capability() {
security_ctx = nullptr;
is_imsi_present = false; is_imsi_present = false;
is_stacs_available = false; is_stacs_available = false;
is_auth_vectors_present = false; is_auth_vectors_present = false;
...@@ -44,7 +42,7 @@ nas_context::nas_context() ...@@ -44,7 +42,7 @@ nas_context::nas_context()
is_common_procedure_for_identification_running = false; is_common_procedure_for_identification_running = false;
is_common_procedure_for_security_mode_control_running = false; is_common_procedure_for_security_mode_control_running = false;
is_common_procedure_for_nas_transport_running = false; is_common_procedure_for_nas_transport_running = false;
security_ctx = nullptr; security_ctx = std::nullopt;
is_current_security_available = false; is_current_security_available = false;
registration_attempt_counter = 0; registration_attempt_counter = 0;
is_imsi_present = false; is_imsi_present = false;
...@@ -62,3 +60,13 @@ nas_context::nas_context() ...@@ -62,3 +60,13 @@ nas_context::nas_context()
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
nas_context::~nas_context() {} nas_context::~nas_context() {}
//------------------------------------------------------------------------------
bool nas_context::get_kamf(
uint8_t index, uint8_t (&k)[AUTH_VECTOR_LENGTH_OCTETS]) const {
if (index >= MAX_5GS_AUTH_VECTORS) return false;
for (uint8_t i = 0; i < AUTH_VECTOR_LENGTH_OCTETS; i++) {
k[i] = kamf[index][i];
}
return true;
}
...@@ -22,10 +22,6 @@ ...@@ -22,10 +22,6 @@
#ifndef _AMF_NAS_CONTEXT_H_ #ifndef _AMF_NAS_CONTEXT_H_
#define _AMF_NAS_CONTEXT_H_ #define _AMF_NAS_CONTEXT_H_
#include <stdint.h>
#include <string>
#include "UESecurityCapability.hpp" #include "UESecurityCapability.hpp"
#include "authentication_algorithms_with_5gaka.hpp" #include "authentication_algorithms_with_5gaka.hpp"
#include "itti.hpp" #include "itti.hpp"
...@@ -110,14 +106,13 @@ class nas_context { ...@@ -110,14 +106,13 @@ class nas_context {
bool is_common_procedure_for_security_mode_control_running; bool is_common_procedure_for_security_mode_control_running;
bool is_common_procedure_for_nas_transport_running; bool is_common_procedure_for_nas_transport_running;
// security related // Security-related parameters
#define MAX_5GS_AUTH_VECTORS 1 #define MAX_5GS_AUTH_VECTORS 1
auc_vector_t _vector[MAX_5GS_AUTH_VECTORS]; // 5GS Authentication vector
_5G_HE_AV_t _5g_he_av[MAX_5GS_AUTH_VECTORS]; // generated by UDM _5G_HE_AV_t _5g_he_av[MAX_5GS_AUTH_VECTORS]; // generated by UDM
_5G_AV_t _5g_av[MAX_5GS_AUTH_VECTORS]; // generated by AUSF _5G_AV_t _5g_av[MAX_5GS_AUTH_VECTORS]; // generated by AUSF
std::string href; std::string href;
uint8_t kamf[MAX_5GS_AUTH_VECTORS][32]; uint8_t kamf[MAX_5GS_AUTH_VECTORS][AUTH_VECTOR_LENGTH_OCTETS];
nas_secu_ctx* security_ctx; // TODO: avoid using naked ptr std::optional<nas_secu_ctx> security_ctx;
bool is_current_security_available; bool is_current_security_available;
int registration_attempt_counter; // used to limit the subsequently reject int registration_attempt_counter; // used to limit the subsequently reject
// registration // registration
...@@ -128,6 +123,8 @@ class nas_context { ...@@ -128,6 +123,8 @@ class nas_context {
bool is_5g_guti_present; bool is_5g_guti_present;
bool is_auth_vectors_present; bool is_auth_vectors_present;
bool to_be_register_by_new_suci; bool to_be_register_by_new_suci;
bool get_kamf(uint8_t index, uint8_t (&k)[AUTH_VECTOR_LENGTH_OCTETS]) const;
}; };
#endif #endif
...@@ -405,8 +405,10 @@ void Authentication_5gaka::derive_knas( ...@@ -405,8 +405,10 @@ void Authentication_5gaka::derive_knas(
} }
void Authentication_5gaka::derive_kgnb( void Authentication_5gaka::derive_kgnb(
uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint8_t* kgnb) { uint32_t uplinkCount, uint8_t accessType,
Logger::amf_n1().debug("derive_kgnb ..."); uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS],
uint8_t (&kgnb)[AUTH_VECTOR_LENGTH_OCTETS]) {
Logger::amf_n1().debug("Derive Kgnb ...");
uint8_t S[20]; uint8_t S[20];
S[0] = 0x6E; S[0] = 0x6E;
*(uint32_t*) (S + 1) = htonl(uplinkCount); *(uint32_t*) (S + 1) = htonl(uplinkCount);
...@@ -417,13 +419,15 @@ void Authentication_5gaka::derive_kgnb( ...@@ -417,13 +419,15 @@ void Authentication_5gaka::derive_kgnb(
S[9] = 0x01; S[9] = 0x01;
// output_wrapper::print_buffer("amf_n1", "inputstring S", S, 10); // output_wrapper::print_buffer("amf_n1", "inputstring S", S, 10);
// output_wrapper::print_buffer("amf_n1", "key KEY", kamf, 32); // output_wrapper::print_buffer("amf_n1", "key KEY", kamf, 32);
kdf(kamf, 32, S, 10, kgnb, 32); kdf(kamf, 32, S, 10, kgnb, AUTH_VECTOR_LENGTH_OCTETS);
// output_wrapper::print_buffer("amf_n1", "kgnb", kgnb, 32); // output_wrapper::print_buffer("amf_n1", "kgnb", kgnb, 32);
// Logger::amf_n1().debug("derive kgnb finished!"); // Logger::amf_n1().debug("derive kgnb finished!");
} }
void Authentication_5gaka::handover_ncc_derive_knh( void Authentication_5gaka::handover_ncc_derive_knh(
uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint8_t* kgnb, uint32_t uplinkCount, uint8_t accessType,
uint8_t* knh, int ncc) { uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS],
uint8_t (&kgnb)[AUTH_VECTOR_LENGTH_OCTETS],
uint8_t (&knh)[AUTH_VECTOR_LENGTH_OCTETS], int ncc) {
Logger::amf_n1().debug("derive_handover_ncc_knh ..."); Logger::amf_n1().debug("derive_handover_ncc_knh ...");
uint8_t S[20], SS[ncc][35]; uint8_t S[20], SS[ncc][35];
S[0] = 0x6E; S[0] = 0x6E;
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#define KASME_LENGTH_OCTETS (32) #define KASME_LENGTH_OCTETS (32)
#define MAC_S_LENGTH (8) #define MAC_S_LENGTH (8)
#define AUTH_VECTOR_LENGTH_OCTETS 32
typedef mpz_t random_t; typedef mpz_t random_t;
typedef mpz_t sqn_t; typedef mpz_t sqn_t;
...@@ -140,11 +142,14 @@ class Authentication_5gaka { ...@@ -140,11 +142,14 @@ class Authentication_5gaka {
algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32], algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t kamf[32],
uint8_t* knas); uint8_t* knas);
static void derive_kgnb( static void derive_kgnb(
uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint32_t uplinkCount, uint8_t accessType,
uint8_t* kgnb); uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS],
uint8_t (&kgnb)[AUTH_VECTOR_LENGTH_OCTETS]);
static void handover_ncc_derive_knh( static void handover_ncc_derive_knh(
uint32_t uplinkCount, uint8_t accessType, uint8_t kamf[32], uint8_t* kgnb, uint32_t uplinkCount, uint8_t accessType,
uint8_t* knh, int ncc); uint8_t kamf[AUTH_VECTOR_LENGTH_OCTETS],
uint8_t (&kgnb)[AUTH_VECTOR_LENGTH_OCTETS],
uint8_t (&knh)[AUTH_VECTOR_LENGTH_OCTETS], int ncc);
static uint8_t* sqn_ms_derive( static uint8_t* sqn_ms_derive(
const uint8_t opc[16], uint8_t* key, uint8_t* auts, uint8_t* rand); const uint8_t opc[16], uint8_t* key, uint8_t* auts, uint8_t* rand);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment