From c028605edd26523e1bf50d458a32162b6ed131a4 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 21:21:27 +0300 Subject: [PATCH 01/56] TODO removed --- src/ue/nas/sm/transport.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ue/nas/sm/transport.cpp b/src/ue/nas/sm/transport.cpp index 4d1b3a4f9..ccf67c105 100644 --- a/src/ue/nas/sm/transport.cpp +++ b/src/ue/nas/sm/transport.cpp @@ -40,8 +40,6 @@ void NasSm::sendSmMessage(int psi, const nas::SmMessage &msg) void NasSm::receiveSmMessage(const nas::SmMessage &msg) { - // TODO: trigger on receive - switch (msg.messageType) { case nas::EMessageType::PDU_SESSION_ESTABLISHMENT_ACCEPT: From b4db214d9d4bf66444820fcb40b76905cd3e317b Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 21:23:58 +0300 Subject: [PATCH 02/56] UE MM some TODO fixes --- src/ue/nas/mm/dereg.cpp | 4 ++-- src/ue/nas/mm/radio.cpp | 5 ----- src/ue/nas/mm/transport.cpp | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/ue/nas/mm/dereg.cpp b/src/ue/nas/mm/dereg.cpp index d2d486b82..11a02faee 100644 --- a/src/ue/nas/mm/dereg.cpp +++ b/src/ue/nas/mm/dereg.cpp @@ -236,13 +236,13 @@ void NasMm::receiveDeregistrationRequest(const nas::DeRegistrationRequestUeTermi if (cause == nas::EMmCause::PLMN_NOT_ALLOWED) { - // todo: add to forbidden plmn + nas::utils::AddToPlmnList(m_usim->m_forbiddenPlmnList, nas::utils::PlmnFrom(*m_usim->m_currentPlmn)); } if (cause == nas::EMmCause::TA_NOT_ALLOWED || cause == nas::EMmCause::ROAMING_NOT_ALLOWED_IN_TA || cause == nas::EMmCause::NO_SUITIBLE_CELLS_IN_TA) { - // todo: add to forbidden tai + nas::utils::AddToTaiList(m_usim->m_forbiddenTaiListRoaming, *m_usim->m_currentTai); } if (cause == nas::EMmCause::ILLEGAL_UE || cause == nas::EMmCause::FIVEG_SERVICES_NOT_ALLOWED) diff --git a/src/ue/nas/mm/radio.cpp b/src/ue/nas/mm/radio.cpp index 45869faf1..0472c7564 100644 --- a/src/ue/nas/mm/radio.cpp +++ b/src/ue/nas/mm/radio.cpp @@ -18,11 +18,6 @@ namespace nr::ue void NasMm::handlePlmnSearchResponse(const std::vector &measures) { - // TODO - // if (m_base->nodeListener) - // m_base->nodeListener->onConnected(app::NodeType::UE, m_base->config->getNodeName(), app::NodeType::GNB, - // gnbName); - if (m_mmSubState != EMmSubState::MM_REGISTERED_PLMN_SEARCH && m_mmSubState != EMmSubState::MM_REGISTERED_NO_CELL_AVAILABLE && m_mmSubState != EMmSubState::MM_DEREGISTERED_PLMN_SEARCH && diff --git a/src/ue/nas/mm/transport.cpp b/src/ue/nas/mm/transport.cpp index 21d8f1c52..d3bc4d1e5 100644 --- a/src/ue/nas/mm/transport.cpp +++ b/src/ue/nas/mm/transport.cpp @@ -169,8 +169,6 @@ void NasMm::receiveNasMessage(const nas::NasMessage &msg) void NasMm::receiveMmMessage(const nas::PlainMmMessage &msg) { - // TODO: trigger on receive - switch (msg.messageType) { case nas::EMessageType::REGISTRATION_ACCEPT: From 3c313a659babe764f2ae92190402153385cf9aa7 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 22:11:18 +0300 Subject: [PATCH 03/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 7c136b44d..f833df994 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -53,7 +53,12 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) msg.selectedNasSecurityAlgorithms.integrity == nas::ETypeOfIntegrityProtectionAlgorithm::IA0 && msg.selectedNasSecurityAlgorithms.ciphering == nas::ETypeOfCipheringAlgorithm::EA0) { - // TODO + if (!hasEmergency()) + { + m_logger->err("IA0 and EA0 cannot be accepted as the UE does not have an emergency"); + reject(nas::EMmCause::SEC_MODE_REJECTED_UNSPECIFIED); + return; + } } int whichCtx = FindSecurityContext(msg.ngKsi.ksi, m_usim->m_currentNsCtx, m_usim->m_nonCurrentNsCtx); From f02456ca1d17866d8d512ad40788d7f2fe1b6612 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 22:19:03 +0300 Subject: [PATCH 04/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index f833df994..2ce624e60 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -55,7 +55,7 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) { if (!hasEmergency()) { - m_logger->err("IA0 and EA0 cannot be accepted as the UE does not have an emergency"); + m_logger->err("[IA0, EA0] cannot be accepted as the UE does not have an emergency"); reject(nas::EMmCause::SEC_MODE_REJECTED_UNSPECIFIED); return; } @@ -101,9 +101,16 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) reject(nas::EMmCause::UE_SECURITY_CAP_MISMATCH); return; } + + if (integrity == nas::ETypeOfIntegrityProtectionAlgorithm::IA0 && !hasEmergency()) + { + m_logger->err("[IA0] cannot be accepted as the UE does not have an emergency"); + reject(nas::EMmCause::SEC_MODE_REJECTED_UNSPECIFIED); + return; + } } - // ============================ Process the security context. ============================ + // ============================ Process the security context ============================ // Assign ABBA (if any) if (msg.abba.has_value()) @@ -127,11 +134,6 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) nsCtx->uplinkCount.overflow = octet2{0}; } - if (msg.selectedNasSecurityAlgorithms.integrity != nas::ETypeOfIntegrityProtectionAlgorithm::IA0) - { - // TODO - } - // Set the new NAS Security Context as current one. (If it is not already the current one) if (whichCtx == 1) m_usim->m_currentNsCtx = std::make_unique(nsCtx->deepCopy()); From a88f4f81121e2588fa39e6045851628799ba0806 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 22:35:47 +0300 Subject: [PATCH 05/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 2ce624e60..d9812d7c9 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -29,6 +29,27 @@ static int FindSecurityContext(int ksi, const std::unique_ptr LocallyDeriveNsc() +{ + auto nsc = std::make_unique(); + nsc->tsc = nas::ETypeOfSecurityContext::NATIVE_SECURITY_CONTEXT; + nsc->ngKsi = 0; + nsc->downlinkCount = {}; + nsc->uplinkCount = {}; + nsc->integrity = nas::ETypeOfIntegrityProtectionAlgorithm::IA0; + nsc->ciphering = nas::ETypeOfCipheringAlgorithm::EA0; + nsc->keys.abba = OctetString::FromSpare(2); + nsc->keys.rand = OctetString::FromSpare(16); + nsc->keys.res = OctetString::FromSpare(16); + nsc->keys.resStar = OctetString::FromSpare(16); + nsc->keys.kAusf = OctetString::FromSpare(32); + nsc->keys.kSeaf = OctetString::FromSpare(32); + nsc->keys.kAmf = OctetString::FromSpare(32); + nsc->keys.kNasInt = OctetString::FromSpare(16); + nsc->keys.kNasEnc = OctetString::FromSpare(16); + return nsc; +} + void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) { m_logger->debug("Security Mode Command received"); @@ -42,6 +63,8 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) // ============================== Check the received ngKSI ============================== + bool locallyDerived = false; + if (!IsValidKsi(msg.ngKsi)) { m_logger->err("Invalid ngKSI received, tsc[%d], ksi[%d]", (int)msg.ngKsi.tsc, msg.ngKsi.ksi); @@ -53,7 +76,13 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) msg.selectedNasSecurityAlgorithms.integrity == nas::ETypeOfIntegrityProtectionAlgorithm::IA0 && msg.selectedNasSecurityAlgorithms.ciphering == nas::ETypeOfCipheringAlgorithm::EA0) { - if (!hasEmergency()) + if (hasEmergency()) + { + m_logger->debug("Locally deriving a current NAS security context"); + m_usim->m_currentNsCtx = LocallyDeriveNsc(); + locallyDerived = true; + } + else { m_logger->err("[IA0, EA0] cannot be accepted as the UE does not have an emergency"); reject(nas::EMmCause::SEC_MODE_REJECTED_UNSPECIFIED); @@ -102,7 +131,7 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) return; } - if (integrity == nas::ETypeOfIntegrityProtectionAlgorithm::IA0 && !hasEmergency()) + if (integrity == nas::ETypeOfIntegrityProtectionAlgorithm::IA0 && !(hasEmergency() || locallyDerived)) { m_logger->err("[IA0] cannot be accepted as the UE does not have an emergency"); reject(nas::EMmCause::SEC_MODE_REJECTED_UNSPECIFIED); From f0ba292ec7aaee6fcf83eb0e3dca068cc84ac78a Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 22:39:02 +0300 Subject: [PATCH 06/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index d9812d7c9..e6a277101 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -100,14 +100,6 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) auto &nsCtx = whichCtx == 0 ? m_usim->m_currentNsCtx : m_usim->m_nonCurrentNsCtx; - // ======================== Check the integrity with new security context ======================== - - { - // TODO: - octet4 mac = msg._macForNewSC; - (void)mac; - } - // ======================== Check replayed UE security capabilities ======================== if (!nas::utils::DeepEqualsIe(msg.replayedUeSecurityCapabilities, createSecurityCapabilityIe())) @@ -139,6 +131,14 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) } } + // ======================== Check the integrity with new security context ======================== + + { + // TODO: + octet4 mac = msg._macForNewSC; + (void)mac; + } + // ============================ Process the security context ============================ // Assign ABBA (if any) From aad4d4c9e9304be359a7eb94e1bef6c7014849fc Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:03:08 +0300 Subject: [PATCH 07/56] Security mode command procedure improvement --- src/lib/nas/msg.hpp | 1 + src/ue/nas/mm/security.cpp | 49 +++++++++++++++++++++++++++++++++---- src/ue/nas/mm/transport.cpp | 3 +++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/lib/nas/msg.hpp b/src/lib/nas/msg.hpp index e1383745f..88cf5d8d6 100644 --- a/src/lib/nas/msg.hpp +++ b/src/lib/nas/msg.hpp @@ -556,6 +556,7 @@ struct SecurityModeCommand : PlainMmMessage std::optional replayedS1UeNetworkCapability{}; octet4 _macForNewSC{}; + OctetString _originalPlainNasPdu{}; SecurityModeCommand(); void onBuild(NasMessageBuilder &b); diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index e6a277101..5355b3379 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -8,6 +8,7 @@ #include "mm.hpp" #include +#include #include namespace nr::ue @@ -133,14 +134,54 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) // ======================== Check the integrity with new security context ======================== + bool clearNasCount = false; + + if (msg.selectedNasSecurityAlgorithms.integrity != nas::ETypeOfIntegrityProtectionAlgorithm::IA0) { - // TODO: - octet4 mac = msg._macForNewSC; - (void)mac; + NasSecurityContext tmpCtx = nsCtx->deepCopy(); + + tmpCtx.integrity = msg.selectedNasSecurityAlgorithms.integrity; + tmpCtx.ciphering = msg.selectedNasSecurityAlgorithms.ciphering; + keys::DeriveNasKeys(tmpCtx); + + uint32_t calculatedMac = + nr::ue::nas_enc::ComputeMac(tmpCtx.integrity, tmpCtx.downlinkCount, tmpCtx.is3gppAccess, false, + tmpCtx.keys.kNasInt, msg._originalPlainNasPdu); + + // First check with the last estimated NAS COUNT + if (calculatedMac != static_cast(msg._macForNewSC)) + { + // Integrity check failed with the last NAS COUNT + // Now check with the NAS COUNT=0 + + tmpCtx.downlinkCount = {}; // assign NAS COUNT=0 + + calculatedMac = nr::ue::nas_enc::ComputeMac(tmpCtx.integrity, tmpCtx.downlinkCount, tmpCtx.is3gppAccess, + false, tmpCtx.keys.kNasInt, msg._originalPlainNasPdu); + + if (calculatedMac != static_cast(msg._macForNewSC)) + { + // If it still mismatched, reject the security mode command + m_logger->err("Security Mode Command integrity check failed"); + reject(nas::EMmCause::SEC_MODE_REJECTED_UNSPECIFIED); + return; + } + else + { + // Otherwise since the integrity passed with NAS COUNT=0, we should clear the NAS COUNT + // as specified in 5.4.2.3 + m_logger->debug("Setting downlink NAS COUNT to 0"); + clearNasCount = true; + } + } } // ============================ Process the security context ============================ + // Clear the NAS count if necessary + if (clearNasCount) + nsCtx->downlinkCount = {}; + // Assign ABBA (if any) if (msg.abba.has_value()) nsCtx->keys.abba = msg.abba->rawData.copy(); @@ -150,8 +191,6 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) nsCtx->ciphering = msg.selectedNasSecurityAlgorithms.ciphering; keys::DeriveNasKeys(*nsCtx); - // m_logger->debug("Derived NAS keys integrity[%s] ciphering[%s]", nsCtx->keys.kNasInt.toHexString().c_str(), - // nsCtx->keys.kNasEnc.toHexString().c_str()); m_logger->debug("Selected integrity[%d] ciphering[%d]", (int)nsCtx->integrity, (int)nsCtx->ciphering); // The UE shall in addition reset the uplink NAS COUNT counter if a) the SECURITY MODE COMMAND message is received diff --git a/src/ue/nas/mm/transport.cpp b/src/ue/nas/mm/transport.cpp index d3bc4d1e5..016421cb9 100644 --- a/src/ue/nas/mm/transport.cpp +++ b/src/ue/nas/mm/transport.cpp @@ -118,6 +118,9 @@ void NasMm::receiveNasMessage(const nas::NasMessage &msg) return; } + ((nas::SecurityModeCommand &)(*smcMsg))._macForNewSC = securedMm.messageAuthenticationCode; + ((nas::SecurityModeCommand &)(*smcMsg))._originalPlainNasPdu = securedMm.plainNasMessage.copy(); + receiveMmMessage((const nas::PlainMmMessage &)(*smcMsg)); return; } From 92cee686a78b7f6027581e36b085fa2d46a398b4 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:15:31 +0300 Subject: [PATCH 08/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 5355b3379..3f28bdcc7 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -178,6 +178,8 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) // ============================ Process the security context ============================ + m_logger->debug("Selected integrity[%d] ciphering[%d]", (int)nsCtx->integrity, (int)nsCtx->ciphering); + // Clear the NAS count if necessary if (clearNasCount) nsCtx->downlinkCount = {}; @@ -191,8 +193,6 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) nsCtx->ciphering = msg.selectedNasSecurityAlgorithms.ciphering; keys::DeriveNasKeys(*nsCtx); - m_logger->debug("Selected integrity[%d] ciphering[%d]", (int)nsCtx->integrity, (int)nsCtx->ciphering); - // The UE shall in addition reset the uplink NAS COUNT counter if a) the SECURITY MODE COMMAND message is received // in order to take a 5G NAS security context into use created after a successful execution of the 5G AKA based // primary authentication and key agreement procedure or the EAP based ... From 372c93c9c991da6926919e48cf65cb9a71ad8b05 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:16:48 +0300 Subject: [PATCH 09/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 3f28bdcc7..4dfe72d71 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -188,6 +188,13 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) if (msg.abba.has_value()) nsCtx->keys.abba = msg.abba->rawData.copy(); + // Handle horizontal derivation + if (msg.additional5gSecurityInformation.has_value() && + msg.additional5gSecurityInformation->hdp == nas::EHorizontalDerivationParameter::REQUIRED) + { + // TODO + } + // Assign selected algorithms to security context, and derive NAS keys nsCtx->integrity = msg.selectedNasSecurityAlgorithms.integrity; nsCtx->ciphering = msg.selectedNasSecurityAlgorithms.ciphering; From b6208f6943b638993bdcba2dd5a97a21ff8d1369 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:21:11 +0300 Subject: [PATCH 10/56] Security mode command procedure improvement --- src/ue/nas/mm/mm.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index 6075a4171..319894342 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -38,10 +38,10 @@ class NasMm // Most recent registration request std::unique_ptr m_lastRegistrationRequest{}; - // Most recent de-registration request - std::unique_ptr m_lastDeregistrationRequest{}; // Most recent service request std::unique_ptr m_lastServiceRequest{}; + // Most recent de-registration request + std::unique_ptr m_lastDeregistrationRequest{}; // Indicates the last de-registration cause EDeregCause m_lastDeregCause{}; // Indicates the last service request cause From 58f9d747309ae9f963ab0c54c10447007f4eed57 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:24:32 +0300 Subject: [PATCH 11/56] Security mode command procedure improvement --- src/ue/nas/mm/mm.hpp | 2 ++ src/ue/nas/mm/register.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index 319894342..38f77e979 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -42,6 +42,8 @@ class NasMm std::unique_ptr m_lastServiceRequest{}; // Most recent de-registration request std::unique_ptr m_lastDeregistrationRequest{}; + // Indicates that last registration request was sent without a NAS security context + bool m_lastRegWithoutNsc{}; // Indicates the last de-registration cause EDeregCause m_lastDeregCause{}; // Indicates the last service request cause diff --git a/src/ue/nas/mm/register.cpp b/src/ue/nas/mm/register.cpp index e587af6ae..84977c429 100644 --- a/src/ue/nas/mm/register.cpp +++ b/src/ue/nas/mm/register.cpp @@ -97,6 +97,7 @@ void NasMm::sendInitialRegistration(EInitialRegCause regCause) // Send the message sendNasMessage(*request); m_lastRegistrationRequest = std::move(request); + m_lastRegWithoutNsc = m_usim->m_currentNsCtx == nullptr; // Process timers m_timers->t3510.start(); @@ -187,6 +188,7 @@ void NasMm::sendMobilityRegistration(ERegUpdateCause updateCause) // Send the message sendNasMessage(*request); m_lastRegistrationRequest = std::move(request); + m_lastRegWithoutNsc = m_usim->m_currentNsCtx == nullptr; // Process timers m_timers->t3510.start(); From 11289b710658d2b490297dea098c60d66d9f96ed Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:27:38 +0300 Subject: [PATCH 12/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 4dfe72d71..abb16c015 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -239,10 +239,21 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) } } - // TODO: Bu service request de olabilir en son hangisiyse, ayrıca son mesaj yerine son unciphered mesaj da olabilir - // See 4.4.6 - resp.nasMessageContainer = nas::IENasMessageContainer{}; - nas::EncodeNasMessage(*m_lastRegistrationRequest, resp.nasMessageContainer->data); + // Handle NAS message container + if (msg.additional5gSecurityInformation.has_value() && + msg.additional5gSecurityInformation->rinmr == nas::ERetransmissionOfInitialNasMessageRequest::REQUESTED) + { + resp.nasMessageContainer = nas::IENasMessageContainer{}; + if (m_mmState == EMmState::MM_REGISTERED_INITIATED && m_lastRegistrationRequest) + nas::EncodeNasMessage(*m_lastRegistrationRequest, resp.nasMessageContainer->data); + else if (m_mmState == EMmState::MM_SERVICE_REQUEST_INITIATED && m_lastServiceRequest) + nas::EncodeNasMessage(*m_lastServiceRequest, resp.nasMessageContainer->data); + } + if (m_lastRegWithoutNsc && m_lastRegistrationRequest) + { + resp.nasMessageContainer = nas::IENasMessageContainer{}; + nas::EncodeNasMessage(*m_lastServiceRequest, resp.nasMessageContainer->data); + } // Send response sendNasMessage(resp); From 1e3683835b7feea02e99e7b88e4f5affe94efe42 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:37:24 +0300 Subject: [PATCH 13/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index abb16c015..6da1efda2 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -252,7 +252,7 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) if (m_lastRegWithoutNsc && m_lastRegistrationRequest) { resp.nasMessageContainer = nas::IENasMessageContainer{}; - nas::EncodeNasMessage(*m_lastServiceRequest, resp.nasMessageContainer->data); + nas::EncodeNasMessage(*m_lastRegistrationRequest, resp.nasMessageContainer->data); } // Send response From 2944a0095d2d2d4214840ca053c6bedfa6aa6571 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:49:55 +0300 Subject: [PATCH 14/56] Security mode command procedure improvement --- src/ue/nas/keys.hpp | 5 +++++ src/ue/nas/mm/security.cpp | 26 ++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/ue/nas/keys.hpp b/src/ue/nas/keys.hpp index afd2c24e0..12e095fd1 100644 --- a/src/ue/nas/keys.hpp +++ b/src/ue/nas/keys.hpp @@ -28,6 +28,11 @@ void DeriveNasKeys(NasSecurityContext &securityContext); */ std::string ConstructServingNetworkName(const Plmn &plmn); +/** + * Derives kAMF to kAMF' in mobility 33.501/A.13 + */ +OctetString DeriveAmfPrimeInMobility(bool isUplink, const NasCount &count, const OctetString &kAmf); + /** * Calculates K_AUSF for 5G-AKA according to given parameters as specified in 3GPP TS 33.501 Annex A.2 */ diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 6da1efda2..e7c2c50c6 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -135,6 +135,9 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) // ======================== Check the integrity with new security context ======================== bool clearNasCount = false; + bool horizontalDeriveNeeded = + msg.additional5gSecurityInformation.has_value() && + msg.additional5gSecurityInformation->hdp == nas::EHorizontalDerivationParameter::REQUIRED; if (msg.selectedNasSecurityAlgorithms.integrity != nas::ETypeOfIntegrityProtectionAlgorithm::IA0) { @@ -142,11 +145,16 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) tmpCtx.integrity = msg.selectedNasSecurityAlgorithms.integrity; tmpCtx.ciphering = msg.selectedNasSecurityAlgorithms.ciphering; + + // Before deriving the keys for temporary NAS security context, concern the horizontal derivation case + // Because 33.501/6.9.3 says integrity check should be performed with the new key + if (horizontalDeriveNeeded) + tmpCtx.keys.kAmf = keys::DeriveAmfPrimeInMobility(true, tmpCtx.uplinkCount, tmpCtx.keys.kAmf); + keys::DeriveNasKeys(tmpCtx); - uint32_t calculatedMac = - nr::ue::nas_enc::ComputeMac(tmpCtx.integrity, tmpCtx.downlinkCount, tmpCtx.is3gppAccess, false, - tmpCtx.keys.kNasInt, msg._originalPlainNasPdu); + uint32_t calculatedMac = nas_enc::ComputeMac(tmpCtx.integrity, tmpCtx.downlinkCount, tmpCtx.is3gppAccess, false, + tmpCtx.keys.kNasInt, msg._originalPlainNasPdu); // First check with the last estimated NAS COUNT if (calculatedMac != static_cast(msg._macForNewSC)) @@ -156,8 +164,8 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) tmpCtx.downlinkCount = {}; // assign NAS COUNT=0 - calculatedMac = nr::ue::nas_enc::ComputeMac(tmpCtx.integrity, tmpCtx.downlinkCount, tmpCtx.is3gppAccess, - false, tmpCtx.keys.kNasInt, msg._originalPlainNasPdu); + calculatedMac = nas_enc::ComputeMac(tmpCtx.integrity, tmpCtx.downlinkCount, tmpCtx.is3gppAccess, false, + tmpCtx.keys.kNasInt, msg._originalPlainNasPdu); if (calculatedMac != static_cast(msg._macForNewSC)) { @@ -189,10 +197,12 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) nsCtx->keys.abba = msg.abba->rawData.copy(); // Handle horizontal derivation - if (msg.additional5gSecurityInformation.has_value() && - msg.additional5gSecurityInformation->hdp == nas::EHorizontalDerivationParameter::REQUIRED) + if (horizontalDeriveNeeded) { - // TODO + m_logger->debug("Performing kAMF' derivation from kAMF in mobility"); + nsCtx->keys.kAmf = keys::DeriveAmfPrimeInMobility(true, nsCtx->uplinkCount, nsCtx->keys.kAmf); + nsCtx->uplinkCount = {}; + nsCtx->downlinkCount = {}; } // Assign selected algorithms to security context, and derive NAS keys From e28656cadbc8f3e065042896466571e26aa3d24b Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:54:40 +0300 Subject: [PATCH 15/56] Security mode command procedure improvement --- src/ue/nas/keys.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ue/nas/keys.cpp b/src/ue/nas/keys.cpp index 7a819380c..8d3f7f5c6 100644 --- a/src/ue/nas/keys.cpp +++ b/src/ue/nas/keys.cpp @@ -81,7 +81,6 @@ std::pair CalculateCkPrimeIkPrime(const OctetString &c s[1] = sqnXorAk.copy(); auto res = crypto::CalculateKdfKey(key, 0x20, s, 2); - ; std::pair ckIk; ckIk.first = res.subCopy(0, ck.length()); @@ -139,4 +138,13 @@ OctetString CalculateResStar(const OctetString &key, const std::string &snn, con return output.subCopy(output.length() - 16); } +OctetString DeriveAmfPrimeInMobility(bool isUplink, const NasCount &count, const OctetString &kAmf) +{ + OctetString params[2]; + params[0] = OctetString::FromOctet(isUplink ? 0x00 : 0x01); + params[1] = OctetString::FromOctet4(count.toOctet4()); + + return crypto::CalculateKdfKey(kAmf, 0x72, params, 2); +} + } // namespace nr::ue::keys \ No newline at end of file From 27b269425e1e4d2157e9a67f1c6040b8e892ad35 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sun, 25 Apr 2021 23:56:00 +0300 Subject: [PATCH 16/56] Security mode command procedure improvement --- src/ue/nas/mm/security.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index e7c2c50c6..427058552 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -213,7 +213,7 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) // The UE shall in addition reset the uplink NAS COUNT counter if a) the SECURITY MODE COMMAND message is received // in order to take a 5G NAS security context into use created after a successful execution of the 5G AKA based // primary authentication and key agreement procedure or the EAP based ... - if (whichCtx == 1) // It is unclear how we can detect this, but checking if it is 'non-current' one. + if (whichCtx == 1) // NOTE: It is unclear how we can detect this, but checking if it is 'non-current' one. { nsCtx->uplinkCount.sqn = 0; nsCtx->uplinkCount.overflow = octet2{0}; From 845e84712c431530eec37b23a306ef5d929baa18 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:02:37 +0300 Subject: [PATCH 17/56] UE generic configuration update improvement --- src/ue/nas/mm/config.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/ue/nas/mm/config.cpp b/src/ue/nas/mm/config.cpp index 4d547094e..3264c631b 100644 --- a/src/ue/nas/mm/config.cpp +++ b/src/ue/nas/mm/config.cpp @@ -9,6 +9,7 @@ #include "mm.hpp" #include +#include namespace nr::ue { @@ -127,6 +128,14 @@ void NasMm::receiveConfigurationUpdate(const nas::ConfigurationUpdateCommand &ms } } + // "If acknowledgement requested is indicated in the Configuration update indication IE in the CONFIGURATION UPDATE + // COMMAND message, the UE shall send a CONFIGURATION UPDATE COMPLETE message." + if (msg.configurationUpdateIndication.has_value() && + msg.configurationUpdateIndication->ack == nas::EAcknowledgement::REQUESTED) + { + sendNasMessage(nas::ConfigurationUpdateComplete{}); + } + // "If the CONFIGURATION UPDATE COMMAND message indicates "registration requested" in the Configuration update // indication IE and:" if (msg.configurationUpdateIndication.has_value() && @@ -137,7 +146,7 @@ void NasMm::receiveConfigurationUpdate(const nas::ConfigurationUpdateCommand &ms if (!hasNewConfig || (msg.allowedNssai.has_value() || msg.configuredNssai.has_value() || msg.networkSlicingIndication.has_value())) { - if (hasEmergency()) // "an emergency PDU session exists," + if (m_sm->anyEmergencySession()) // "an emergency PDU session exists," { // "the UE shall, after the completion of the generic UE configuration // update procedure and after the emergency PDU session is released, release the existing N1 NAS @@ -163,14 +172,6 @@ void NasMm::receiveConfigurationUpdate(const nas::ConfigurationUpdateCommand &ms // TODO } } - - // "If acknowledgement requested is indicated in the Configuration update indication IE in the CONFIGURATION UPDATE - // COMMAND message, the UE shall send a CONFIGURATION UPDATE COMPLETE message." - if (msg.configurationUpdateIndication.has_value() && - msg.configurationUpdateIndication->ack == nas::EAcknowledgement::REQUESTED) - { - sendNasMessage(nas::ConfigurationUpdateComplete{}); - } } } // namespace nr::ue From 76c64f41fbdb4211a72c4a80ae389c0764291a12 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:13:30 +0300 Subject: [PATCH 18/56] UE generic configuration update abnormla case 'c' handling --- src/ue/nas/mm/config.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ue/nas/mm/config.cpp b/src/ue/nas/mm/config.cpp index 3264c631b..ada775a52 100644 --- a/src/ue/nas/mm/config.cpp +++ b/src/ue/nas/mm/config.cpp @@ -16,6 +16,18 @@ namespace nr::ue void NasMm::receiveConfigurationUpdate(const nas::ConfigurationUpdateCommand &msg) { + // Abnormal case: 5.4.4.5, c) Generic UE configuration update and de-registration procedure collision + if (m_mmState == EMmState::MM_DEREGISTERED_INITIATED) + { + // "If the UE receives CONFIGURATION UPDATE COMMAND message after sending a DEREGISTRATION REQUEST message and + // the access type included in the DEREGISTRATION REQUEST message is same as the access in which the + // CONFIGURATION UPDATE COMMAND message is received, then the UE shall ignore the CONFIGURATION UPDATE COMMAND + // message and proceed with the de-registration procedure. Otherwise, the UE shall proceed with both the + // procedures." + m_logger->warn("Configuration Update Command ignored because of the De-registration procedure collusion"); + return; + } + // Indicates there exists at least one configuration to be updated bool hasNewConfig = false; From a7e067b8e680eeb1c131e9f6fc049be8e9fcb83b Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:24:18 +0300 Subject: [PATCH 19/56] UE Authentication refactor --- src/ue/nas/mm/auth.cpp | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index ceaf89c2e..b85d6c8c1 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -9,7 +9,6 @@ #include "mm.hpp" #include -static const bool IGNORE_CONTROLS_FAILURES = false; static const bool USE_SQN_HACK = true; // TODO namespace nr::ue @@ -62,9 +61,6 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms // Log.warning(Tag.CONFIG, "USE_SQN_HACK: %s", USE_SQN_HACK); } - if (IGNORE_CONTROLS_FAILURES) - m_logger->warn("IGNORE_CONTROLS_FAILURES enabled"); - if (USE_SQN_HACK) { auto ak = calculateMilenage(OctetString::FromSpare(6), receivedRand).ak; @@ -106,7 +102,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms // m_logger->debug("calculated kaut: %s", kaut.toHexString().c_str()); // Control received KDF - if (!IGNORE_CONTROLS_FAILURES && receivedKdf != 1) + if (receivedKdf != 1) { ueRejectionTimers(); @@ -148,7 +144,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms eapResponse->attributes.putClientErrorCode(0); } - if (!IGNORE_CONTROLS_FAILURES && eapResponse != nullptr) + if (eapResponse != nullptr) { ueRejectionTimers(); @@ -168,21 +164,18 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms m_logger->err("AT_MAC failure in EAP AKA'. expected: %s received: %s", expectedMac.toHexString().c_str(), receivedMac.toHexString().c_str()); - if (!IGNORE_CONTROLS_FAILURES) - { - ueRejectionTimers(); + ueRejectionTimers(); - auto eapResponse = std::make_unique(eap::ECode::RESPONSE, receivedEap.id, - eap::ESubType::AKA_CLIENT_ERROR); - eapResponse->attributes.putClientErrorCode(0); + auto eapResponse = std::make_unique(eap::ECode::RESPONSE, receivedEap.id, + eap::ESubType::AKA_CLIENT_ERROR); + eapResponse->attributes.putClientErrorCode(0); - nas::AuthenticationReject response; - response.eapMessage = nas::IEEapMessage{}; - response.eapMessage->eap = std::move(eapResponse); + nas::AuthenticationReject response; + response.eapMessage = nas::IEEapMessage{}; + response.eapMessage->eap = std::move(eapResponse); - sendNasMessage(response); - return; - } + sendNasMessage(response); + return; } // Create new partial native NAS security context and continue key derivation @@ -238,9 +231,6 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & // Log.warning(Tag.CONFIG, "USE_SQN_HACK: %s", USE_SQN_HACK); } - if (IGNORE_CONTROLS_FAILURES) - m_logger->warn("IGNORE_CONTROLS_FAILURES enabled"); - if (!msg.authParamRAND.has_value() || !msg.authParamAUTN.has_value()) { sendFailure(nas::EMmCause::SEMANTICALLY_INCORRECT_MESSAGE); @@ -275,7 +265,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto autnCheck = validateAutn(milenageAk, milenageMac, autn); - if (IGNORE_CONTROLS_FAILURES || autnCheck == EAutnValidationRes::OK) + if (autnCheck == EAutnValidationRes::OK) { // Create new partial native NAS security context and continue with key derivation m_usim->m_nonCurrentNsCtx = std::make_unique(); From 6a0ad8421a57e0cde83366a83a3671a46eb5c558 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:28:01 +0300 Subject: [PATCH 20/56] UE Authentication refactor --- src/ue/nas/mm/auth.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index b85d6c8c1..77398b13c 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -226,11 +226,6 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & sendNasMessage(resp); }; - if (USE_SQN_HACK) - { - // Log.warning(Tag.CONFIG, "USE_SQN_HACK: %s", USE_SQN_HACK); - } - if (!msg.authParamRAND.has_value() || !msg.authParamAUTN.has_value()) { sendFailure(nas::EMmCause::SEMANTICALLY_INCORRECT_MESSAGE); From 05ccc563cf7610a4ea6cfc1080093c919646b999 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:28:36 +0300 Subject: [PATCH 21/56] UE Authentication refactor --- src/ue/nas/mm/auth.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 77398b13c..18e6585ea 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -253,11 +253,6 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto sqnXorAk = OctetString::Xor(m_usim->m_sqn, milenageAk); auto snn = keys::ConstructServingNetworkName(*m_usim->m_currentPlmn); - // m_logger->debug("Calculated res[%s] ck[%s] ik[%s] ak[%s] mac_a[%s]", res.toHexString().c_str(), - // ck.toHexString().c_str(), ik.toHexString().c_str(), milenageAk.toHexString().c_str(), - // milenageMac.toHexString().c_str()); - // m_logger->debug("Used snn[%s] sqn[%s]", snn.c_str(), m_usim->m_sqn.toHexString().c_str()); - auto autnCheck = validateAutn(milenageAk, milenageMac, autn); if (autnCheck == EAutnValidationRes::OK) @@ -274,11 +269,6 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & keys::DeriveKeysSeafAmf(*m_base->config, *m_usim->m_currentPlmn, *m_usim->m_nonCurrentNsCtx); - // m_logger->debug("Derived kSeaf[%s] kAusf[%s] kAmf[%s]", - // m_usim->m_nonCurrentNsCtx->keys.kSeaf.toHexString().c_str(), - // m_usim->m_nonCurrentNsCtx->keys.kAusf.toHexString().c_str(), - // m_usim->m_nonCurrentNsCtx->keys.kAmf.toHexString().c_str()); - // Send response nas::AuthenticationResponse resp; resp.authenticationResponseParameter = nas::IEAuthenticationResponseParameter{}; From bdf48526a4d090a7930b86903bb139aa21a91f9a Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:29:29 +0300 Subject: [PATCH 22/56] UE Authentication refactor --- src/ue/nas/mm/auth.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 18e6585ea..920b21e68 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -235,8 +235,6 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto &rand = msg.authParamRAND->value; auto &autn = msg.authParamAUTN->value; - // m_logger->debug("Received rand[%s] autn[%s]", rand.toHexString().c_str(), autn.toHexString().c_str()); - if (USE_SQN_HACK) { auto ak = calculateMilenage(OctetString::FromSpare(6), rand).ak; From 77507ca23aba135b94da9ce6fe1570fad3d4d6ec Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:42:20 +0300 Subject: [PATCH 23/56] UE Authentication refactor --- src/ue/nas/mm/auth.cpp | 13 +++++++++++-- src/ue/nas/mm/service.cpp | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 920b21e68..7b2b83ba1 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -7,6 +7,8 @@ // #include "mm.hpp" + +#include #include static const bool USE_SQN_HACK = true; // TODO @@ -166,8 +168,8 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms ueRejectionTimers(); - auto eapResponse = std::make_unique(eap::ECode::RESPONSE, receivedEap.id, - eap::ESubType::AKA_CLIENT_ERROR); + auto eapResponse = + std::make_unique(eap::ECode::RESPONSE, receivedEap.id, eap::ESubType::AKA_CLIENT_ERROR); eapResponse->attributes.putClientErrorCode(0); nas::AuthenticationReject response; @@ -221,6 +223,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &msg) { auto sendFailure = [this](nas::EMmCause cause) { + m_logger->err("Rejecting Authentication Request with cause: %s", nas::utils::EnumToString(cause)); nas::AuthenticationFailure resp{}; resp.mmCause.value = cause; sendNasMessage(resp); @@ -232,6 +235,12 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & return; } + if (msg.authParamRAND->value.length() != 16 || msg.authParamAUTN->value.length() != 16) + { + sendFailure(nas::EMmCause::SEMANTICALLY_INCORRECT_MESSAGE); + return; + } + auto &rand = msg.authParamRAND->value; auto &autn = msg.authParamAUTN->value; diff --git a/src/ue/nas/mm/service.cpp b/src/ue/nas/mm/service.cpp index 8a7b8db5b..683f90b7d 100644 --- a/src/ue/nas/mm/service.cpp +++ b/src/ue/nas/mm/service.cpp @@ -7,6 +7,7 @@ // #include "mm.hpp" + #include #include From 8681c20df1e3ecba106faaeb67f9716b2e7ceae1 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:50:13 +0300 Subject: [PATCH 24/56] UE Authentication refactor --- src/ue/nas/mm/auth.cpp | 18 +++++++++--------- src/ue/nas/mm/security.cpp | 2 +- src/ue/nas/usim.cpp | 2 ++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 7b2b83ba1..1cd08fbaa 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -223,7 +223,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &msg) { auto sendFailure = [this](nas::EMmCause cause) { - m_logger->err("Rejecting Authentication Request with cause: %s", nas::utils::EnumToString(cause)); + m_logger->err("Sending Authentication Failure with cause [%s]", nas::utils::EnumToString(cause)); nas::AuthenticationFailure resp{}; resp.mmCause.value = cause; sendNasMessage(resp); @@ -384,6 +384,13 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString OctetString receivedAMF = autn.subCopy(6, 2); OctetString receivedMAC = autn.subCopy(8, 8); + // Verify that the received sequence number SQN is in the correct range + if (!checkSqn(receivedSQN)) + { + m_logger->debug("AUTN validation SQN not acceptable"); + return EAutnValidationRes::SYNCHRONISATION_FAILURE; + } + // Check MAC if (receivedMAC != mac) { @@ -400,17 +407,10 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString return EAutnValidationRes::AMF_SEPARATION_BIT_FAILURE; } - // Verify that the received sequence number SQN is in the correct range - if (!checkSqn(receivedSQN)) - { - m_logger->err("AUTN validation SQN not acceptable"); - return EAutnValidationRes::SYNCHRONISATION_FAILURE; - } - return EAutnValidationRes::OK; } -bool NasMm::checkSqn(const OctetString &) +bool NasMm::checkSqn(const OctetString &sqn) { // TODO: // Verify the freshness of sequence numbers to determine whether the specified sequence number is diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 427058552..7792f40c8 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -59,7 +59,7 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) nas::SecurityModeReject resp; resp.mmCause.value = cause; sendNasMessage(resp); - m_logger->err("Rejecting Security Mode Command with cause: %s", nas::utils::EnumToString(cause)); + m_logger->err("Rejecting Security Mode Command with cause [%s]", nas::utils::EnumToString(cause)); }; // ============================== Check the received ngKSI ============================== diff --git a/src/ue/nas/usim.cpp b/src/ue/nas/usim.cpp index 9d1cef973..80316df7c 100644 --- a/src/ue/nas/usim.cpp +++ b/src/ue/nas/usim.cpp @@ -19,6 +19,8 @@ void ue::Usim::initialize(bool hasSupi, const UeConfig::Initials &initials) m_defConfiguredNssai = initials.defaultConfiguredNssai; m_configuredNssai = initials.configuredNssai; + + m_sqn = OctetString::FromSpare(6); } bool Usim::isValid() From f47f7c4b27f76a1e8e61a18a2a573e3c2c951341 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 13:58:10 +0300 Subject: [PATCH 25/56] UE Authentication refactor --- src/ue/nas/mm/auth.cpp | 16 ++++++++-------- src/ue/nas/mm/security.cpp | 3 --- src/ue/nas/usim.hpp | 3 +++ src/ue/types.hpp | 7 ------- 4 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 1cd08fbaa..611e86f2d 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -187,9 +187,9 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms m_usim->m_nonCurrentNsCtx = std::make_unique(); m_usim->m_nonCurrentNsCtx->tsc = msg.ngKSI.tsc; m_usim->m_nonCurrentNsCtx->ngKsi = msg.ngKSI.ksi; - m_usim->m_nonCurrentNsCtx->keys.rand = std::move(receivedRand); - m_usim->m_nonCurrentNsCtx->keys.res = std::move(res); - m_usim->m_nonCurrentNsCtx->keys.resStar = {}; + m_usim->m_rand = std::move(receivedRand); + m_usim->m_res = std::move(res); + m_usim->m_resStar = {}; m_usim->m_nonCurrentNsCtx->keys.kAusf = std::move(kAusf); m_usim->m_nonCurrentNsCtx->keys.abba = msg.abba.rawData.copy(); @@ -202,7 +202,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms { auto *akaPrimeResponse = new eap::EapAkaPrime(eap::ECode::RESPONSE, receivedEap.id, eap::ESubType::AKA_CHALLENGE); - akaPrimeResponse->attributes.putRes(m_usim->m_nonCurrentNsCtx->keys.res); + akaPrimeResponse->attributes.putRes(m_usim->m_res); akaPrimeResponse->attributes.putMac(OctetString::FromSpare(16)); // Dummy mac for now akaPrimeResponse->attributes.putKdf(1); @@ -268,9 +268,9 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & m_usim->m_nonCurrentNsCtx = std::make_unique(); m_usim->m_nonCurrentNsCtx->tsc = msg.ngKSI.tsc; m_usim->m_nonCurrentNsCtx->ngKsi = msg.ngKSI.ksi; - m_usim->m_nonCurrentNsCtx->keys.rand = rand.copy(); - m_usim->m_nonCurrentNsCtx->keys.resStar = keys::CalculateResStar(ckIk, snn, rand, res); - m_usim->m_nonCurrentNsCtx->keys.res = std::move(res); + m_usim->m_rand = rand.copy(); + m_usim->m_resStar = keys::CalculateResStar(ckIk, snn, rand, res); + m_usim->m_res = std::move(res); m_usim->m_nonCurrentNsCtx->keys.kAusf = keys::CalculateKAusfFor5gAka(ck, ik, snn, sqnXorAk); m_usim->m_nonCurrentNsCtx->keys.abba = msg.abba.rawData.copy(); @@ -279,7 +279,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & // Send response nas::AuthenticationResponse resp; resp.authenticationResponseParameter = nas::IEAuthenticationResponseParameter{}; - resp.authenticationResponseParameter->rawData = m_usim->m_nonCurrentNsCtx->keys.resStar.copy(); + resp.authenticationResponseParameter->rawData = m_usim->m_resStar.copy(); sendNasMessage(resp); } else if (autnCheck == EAutnValidationRes::MAC_FAILURE) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 7792f40c8..952179567 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -40,9 +40,6 @@ static std::unique_ptr LocallyDeriveNsc() nsc->integrity = nas::ETypeOfIntegrityProtectionAlgorithm::IA0; nsc->ciphering = nas::ETypeOfCipheringAlgorithm::EA0; nsc->keys.abba = OctetString::FromSpare(2); - nsc->keys.rand = OctetString::FromSpare(16); - nsc->keys.res = OctetString::FromSpare(16); - nsc->keys.resStar = OctetString::FromSpare(16); nsc->keys.kAusf = OctetString::FromSpare(32); nsc->keys.kSeaf = OctetString::FromSpare(32); nsc->keys.kAmf = OctetString::FromSpare(32); diff --git a/src/ue/nas/usim.hpp b/src/ue/nas/usim.hpp index da70d118a..86d31ce1f 100644 --- a/src/ue/nas/usim.hpp +++ b/src/ue/nas/usim.hpp @@ -47,6 +47,9 @@ class Usim std::unique_ptr m_currentNsCtx{}; std::unique_ptr m_nonCurrentNsCtx{}; OctetString m_sqn{}; + OctetString m_rand{}; + OctetString m_res{}; + OctetString m_resStar{}; // NSSAI related NetworkSlice m_defConfiguredNssai{}; diff --git a/src/ue/types.hpp b/src/ue/types.hpp index ae13c5c25..e2ec62d24 100644 --- a/src/ue/types.hpp +++ b/src/ue/types.hpp @@ -303,10 +303,6 @@ struct UeKeys { OctetString abba{}; - OctetString rand{}; - OctetString res{}; - OctetString resStar{}; // used in 5G-AKA - OctetString kAusf{}; OctetString kSeaf{}; OctetString kAmf{}; @@ -316,9 +312,6 @@ struct UeKeys [[nodiscard]] UeKeys deepCopy() const { UeKeys keys; - keys.rand = rand.subCopy(0); - keys.res = res.subCopy(0); - keys.resStar = resStar.subCopy(0); keys.kAusf = kAusf.subCopy(0); keys.kSeaf = kSeaf.subCopy(0); keys.kAmf = kAmf.subCopy(0); From 68448016a713cc0e10b85009072d234ed33f9e8f Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 14:20:05 +0300 Subject: [PATCH 26/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 62 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 611e86f2d..d57b64fe7 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -224,11 +224,21 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & { auto sendFailure = [this](nas::EMmCause cause) { m_logger->err("Sending Authentication Failure with cause [%s]", nas::utils::EnumToString(cause)); + + m_usim->m_rand = {}; + m_usim->m_res = {}; + m_usim->m_resStar = {}; + + m_timers->t3516.stop(); + nas::AuthenticationFailure resp{}; resp.mmCause.value = cause; + sendNasMessage(resp); }; + // ========================== Check the received parameters syntactically ========================== + if (!msg.authParamRAND.has_value() || !msg.authParamAUTN.has_value()) { sendFailure(nas::EMmCause::SEMANTICALLY_INCORRECT_MESSAGE); @@ -241,6 +251,31 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & return; } + // =================================== Check the received ngKSI =================================== + + if (msg.ngKSI.tsc == nas::ETypeOfSecurityContext::MAPPED_SECURITY_CONTEXT) + { + m_logger->err("Mapped security context not supported"); + sendFailure(nas::EMmCause::UNSPECIFIED_PROTOCOL_ERROR); + return; + } + + if (msg.ngKSI.ksi == nas::IENasKeySetIdentifier::NOT_AVAILABLE_OR_RESERVED) + { + m_logger->err("Invalid ngKSI value received"); + sendFailure(nas::EMmCause::UNSPECIFIED_PROTOCOL_ERROR); + return; + } + + if ((m_usim->m_currentNsCtx && m_usim->m_currentNsCtx->ngKsi == msg.ngKSI.ksi) || + (m_usim->m_nonCurrentNsCtx && m_usim->m_nonCurrentNsCtx->ngKsi == msg.ngKSI.ksi)) + { + sendFailure(nas::EMmCause::NGKSI_ALREADY_IN_USE); + return; + } + + // ============================================ Others ============================================ + auto &rand = msg.authParamRAND->value; auto &autn = msg.authParamAUTN->value; @@ -264,13 +299,15 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & if (autnCheck == EAutnValidationRes::OK) { + // Store the relevant parameters + m_usim->m_rand = rand.copy(); + m_usim->m_resStar = keys::CalculateResStar(ckIk, snn, rand, res); + m_usim->m_res = std::move(res); + // Create new partial native NAS security context and continue with key derivation m_usim->m_nonCurrentNsCtx = std::make_unique(); m_usim->m_nonCurrentNsCtx->tsc = msg.ngKSI.tsc; m_usim->m_nonCurrentNsCtx->ngKsi = msg.ngKSI.ksi; - m_usim->m_rand = rand.copy(); - m_usim->m_resStar = keys::CalculateResStar(ckIk, snn, rand, res); - m_usim->m_res = std::move(res); m_usim->m_nonCurrentNsCtx->keys.kAusf = keys::CalculateKAusfFor5gAka(ck, ik, snn, sqnXorAk); m_usim->m_nonCurrentNsCtx->keys.abba = msg.abba.rawData.copy(); @@ -294,7 +331,8 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else { - sendFailure(nas::EMmCause::UNSPECIFIED_PROTOCOL_ERROR); + // the other case, separation bit mismatched + sendFailure(nas::EMmCause::NON_5G_AUTHENTICATION_UNACCEPTABLE); } } @@ -384,6 +422,14 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString OctetString receivedAMF = autn.subCopy(6, 2); OctetString receivedMAC = autn.subCopy(8, 8); + // TS 33.501: An ME accessing 5G shall check during authentication that the "separation bit" in the AMF field + // of AUTN is set to 1. The "separation bit" is bit 0 of the AMF field of AUTN. + if (receivedAMF.get(0).bit(7) != 1) + { + m_logger->err("AUTN validation SEP-BIT failure. expected: 1, received: 0"); + return EAutnValidationRes::AMF_SEPARATION_BIT_FAILURE; + } + // Verify that the received sequence number SQN is in the correct range if (!checkSqn(receivedSQN)) { @@ -399,14 +445,6 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString return EAutnValidationRes::MAC_FAILURE; } - // TS 33.501: An ME accessing 5G shall check during authentication that the "separation bit" in the AMF field - // of AUTN is set to 1. The "separation bit" is bit 0 of the AMF field of AUTN. - if (receivedAMF.get(0).bit(7) != 1) - { - m_logger->err("AUTN validation SEP-BIT failure. expected: 1, received: 0"); - return EAutnValidationRes::AMF_SEPARATION_BIT_FAILURE; - } - return EAutnValidationRes::OK; } From c50e6308dac2cb2335de9c12dfd9615098d2f514 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 14:27:08 +0300 Subject: [PATCH 27/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index d57b64fe7..daa76136a 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -222,18 +222,30 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &msg) { - auto sendFailure = [this](nas::EMmCause cause) { - m_logger->err("Sending Authentication Failure with cause [%s]", nas::utils::EnumToString(cause)); + auto sendFailure = [this](nas::EMmCause cause, std::optional &&auts = std::nullopt) { + if (cause == nas::EMmCause::SYNCH_FAILURE) + m_logger->debug("Sending Authentication Failure due to SQN out of range"); + else + m_logger->err("Sending Authentication Failure with cause [%s]", nas::utils::EnumToString(cause)); + // Clear parameters stored in volatile memory of ME m_usim->m_rand = {}; m_usim->m_res = {}; m_usim->m_resStar = {}; + // Stop T3516 if running m_timers->t3516.stop(); + // Send Authentication Failure nas::AuthenticationFailure resp{}; resp.mmCause.value = cause; + if (auts.has_value()) + { + resp.authenticationFailureParameter = {}; + resp.authenticationFailureParameter->rawData = std::move(*auts); + } + sendNasMessage(resp); }; @@ -325,9 +337,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) { - // TODO - m_logger->err("SYNCHRONISATION_FAILURE case not implemented yet in AUTN validation"); - sendFailure(nas::EMmCause::UNSPECIFIED_PROTOCOL_ERROR); + sendFailure(nas::EMmCause::SYNCH_FAILURE); } else { From 8b37a2bc5171d47e43b4a2087b753b854ca93e11 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 14:32:08 +0300 Subject: [PATCH 28/56] UE authentication procedure improvements --- src/ue/nas/keys.cpp | 7 +++++++ src/ue/nas/keys.hpp | 7 ++++++- src/ue/nas/mm/auth.cpp | 3 ++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ue/nas/keys.cpp b/src/ue/nas/keys.cpp index 8d3f7f5c6..2e5acf497 100644 --- a/src/ue/nas/keys.cpp +++ b/src/ue/nas/keys.cpp @@ -147,4 +147,11 @@ OctetString DeriveAmfPrimeInMobility(bool isUplink, const NasCount &count, const return crypto::CalculateKdfKey(kAmf, 0x72, params, 2); } +OctetString CalculateAuts(const OctetString &sqn, const OctetString &ak, const OctetString &macS) +{ + OctetString auts = OctetString::Xor(sqn, ak); + auts.append(macS); + return auts; +} + } // namespace nr::ue::keys \ No newline at end of file diff --git a/src/ue/nas/keys.hpp b/src/ue/nas/keys.hpp index 12e095fd1..7fa9207c5 100644 --- a/src/ue/nas/keys.hpp +++ b/src/ue/nas/keys.hpp @@ -71,4 +71,9 @@ OctetString CalculateKAusfForEapAkaPrime(const OctetString &mk); OctetString CalculateResStar(const OctetString &key, const std::string &snn, const OctetString &rand, const OctetString &res); -} // namespace nr::ue::keys \ No newline at end of file +/* + * Calculates AUTS according to the given parameters + */ +OctetString CalculateAuts(const OctetString &sqn, const OctetString &ak, const OctetString &macS); + +} // namespace nr::ue::keys diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index daa76136a..183a36d52 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -304,6 +304,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto ckIk = OctetString::Concat(ck, ik); auto &milenageAk = milenage.ak; auto &milenageMac = milenage.mac_a; + auto &milenageMacS = milenage.mac_s; auto sqnXorAk = OctetString::Xor(m_usim->m_sqn, milenageAk); auto snn = keys::ConstructServingNetworkName(*m_usim->m_currentPlmn); @@ -337,7 +338,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) { - sendFailure(nas::EMmCause::SYNCH_FAILURE); + sendFailure(nas::EMmCause::SYNCH_FAILURE, keys::CalculateAuts(m_usim->m_sqn, milenageAk, milenageMacS)); } else { From 73350780d514fa5efbc99313159cda80db17a00c Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 14:48:21 +0300 Subject: [PATCH 29/56] Typo fix --- src/lib/crypt/milenage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/crypt/milenage.cpp b/src/lib/crypt/milenage.cpp index 7e720691a..ce29766ba 100644 --- a/src/lib/crypt/milenage.cpp +++ b/src/lib/crypt/milenage.cpp @@ -27,10 +27,10 @@ Milenage Calculate(const OctetString &opc, const OctetString &key, const OctetSt r.ak_r = OctetString::FromSpare(6); if (milenage_f1(opc.data(), key.data(), rand.data(), sqn.data(), amf.data(), r.mac_a.data(), r.mac_s.data())) - throw std::runtime_error("OPC calculation failed"); + throw std::runtime_error("Milenage calculation failed"); if (milenage_f2345(opc.data(), key.data(), rand.data(), r.res.data(), r.ck.data(), r.ik.data(), r.ak.data(), r.ak_r.data())) - throw std::runtime_error("OPC calculation failed"); + throw std::runtime_error("Milenage calculation failed"); return r; } From 221332c29763c7d2133a706db399bcb5dd6583ed Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 14:49:37 +0300 Subject: [PATCH 30/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 183a36d52..7f83112d9 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -242,7 +242,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & if (auts.has_value()) { - resp.authenticationFailureParameter = {}; + resp.authenticationFailureParameter = nas::IEAuthenticationFailureParameter{}; resp.authenticationFailureParameter->rawData = std::move(*auts); } @@ -444,7 +444,6 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString // Verify that the received sequence number SQN is in the correct range if (!checkSqn(receivedSQN)) { - m_logger->debug("AUTN validation SQN not acceptable"); return EAutnValidationRes::SYNCHRONISATION_FAILURE; } From 09f5e99d95eae64553e98c6b3779319ede794b16 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 15:16:41 +0300 Subject: [PATCH 31/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 22 +++++++++++++--------- src/ue/nas/mm/mm.hpp | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 7f83112d9..19fdbe880 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -65,11 +65,11 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms if (USE_SQN_HACK) { - auto ak = calculateMilenage(OctetString::FromSpare(6), receivedRand).ak; + auto ak = calculateMilenage(OctetString::FromSpare(6), receivedRand, false).ak; m_usim->m_sqn = OctetString::Xor(receivedAutn.subCopy(0, 6), ak); } - auto milenage = calculateMilenage(m_usim->m_sqn, receivedRand); + auto milenage = calculateMilenage(m_usim->m_sqn, receivedRand, false); auto &res = milenage.res; auto &ck = milenage.ck; auto &ik = milenage.ik; @@ -293,18 +293,17 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & if (USE_SQN_HACK) { - auto ak = calculateMilenage(OctetString::FromSpare(6), rand).ak; + auto ak = calculateMilenage(OctetString::FromSpare(6), rand, false).ak; m_usim->m_sqn = OctetString::Xor(autn.subCopy(0, 6), ak); } - auto milenage = calculateMilenage(m_usim->m_sqn, rand); + auto milenage = calculateMilenage(m_usim->m_sqn, rand, false); auto &res = milenage.res; auto &ck = milenage.ck; auto &ik = milenage.ik; auto ckIk = OctetString::Concat(ck, ik); auto &milenageAk = milenage.ak; auto &milenageMac = milenage.mac_a; - auto &milenageMacS = milenage.mac_s; auto sqnXorAk = OctetString::Xor(m_usim->m_sqn, milenageAk); auto snn = keys::ConstructServingNetworkName(*m_usim->m_currentPlmn); @@ -338,7 +337,9 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) { - sendFailure(nas::EMmCause::SYNCH_FAILURE, keys::CalculateAuts(m_usim->m_sqn, milenageAk, milenageMacS)); + auto milenageForSync = calculateMilenage(m_usim->m_sqn, rand, true); + auto auts = keys::CalculateAuts(m_usim->m_sqn, milenageForSync.ak_r, milenageForSync.mac_s); + sendFailure(nas::EMmCause::SYNCH_FAILURE, std::move(auts)); } else { @@ -466,12 +467,15 @@ bool NasMm::checkSqn(const OctetString &sqn) return true; } -crypto::milenage::Milenage NasMm::calculateMilenage(const OctetString &sqn, const OctetString &rand) +crypto::milenage::Milenage NasMm::calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf) { + OctetString amf = dummyAmf ? OctetString::FromSpare(2) : m_base->config->amf.copy(); + if (m_base->config->opType == OpType::OPC) - return crypto::milenage::Calculate(m_base->config->opC, m_base->config->key, rand, sqn, m_base->config->amf); + return crypto::milenage::Calculate(m_base->config->opC, m_base->config->key, rand, sqn, amf); + OctetString opc = crypto::milenage::CalculateOpC(m_base->config->opC, m_base->config->key); - return crypto::milenage::Calculate(opc, m_base->config->key, rand, sqn, m_base->config->amf); + return crypto::milenage::Calculate(opc, m_base->config->key, rand, sqn, amf); } } // namespace nr::ue \ No newline at end of file diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index 38f77e979..7d0ce291b 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -116,7 +116,7 @@ class NasMm void receiveEapResponseMessage(const eap::Eap &eap); EAutnValidationRes validateAutn(const OctetString &ak, const OctetString &mac, const OctetString &autn); bool checkSqn(const OctetString &sqn); - crypto::milenage::Milenage calculateMilenage(const OctetString &sqn, const OctetString &rand); + crypto::milenage::Milenage calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf); private: /* Security */ void receiveSecurityModeCommand(const nas::SecurityModeCommand &msg); From 1df20531d298edb103fe90ca6539f1101e092807 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 15:19:54 +0300 Subject: [PATCH 32/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 19fdbe880..3f5a11274 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -223,9 +223,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &msg) { auto sendFailure = [this](nas::EMmCause cause, std::optional &&auts = std::nullopt) { - if (cause == nas::EMmCause::SYNCH_FAILURE) - m_logger->debug("Sending Authentication Failure due to SQN out of range"); - else + if (cause != nas::EMmCause::SYNCH_FAILURE) m_logger->err("Sending Authentication Failure with cause [%s]", nas::utils::EnumToString(cause)); // Clear parameters stored in volatile memory of ME From 78937f5e4df963a85f9ea26747c32819b100856f Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 15:36:53 +0300 Subject: [PATCH 33/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 3f5a11274..c3fd32543 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -449,7 +449,7 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString // Check MAC if (receivedMAC != mac) { - m_logger->err("AUTN validation MAC mismatch. expected: %s received: %s", mac.toHexString().c_str(), + m_logger->err("AUTN validation MAC mismatch. expected [%s] received [%s]", mac.toHexString().c_str(), receivedMAC.toHexString().c_str()); return EAutnValidationRes::MAC_FAILURE; } From 200a27638dbd18bae4f74d95a11e1e4b281c20f6 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 15:41:36 +0300 Subject: [PATCH 34/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 18 +----------------- src/ue/nas/mm/mm.hpp | 1 - src/ue/nas/usim.cpp | 6 ++++++ src/ue/nas/usim.hpp | 7 ++++++- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index c3fd32543..5a90e7c64 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -289,12 +289,6 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto &rand = msg.authParamRAND->value; auto &autn = msg.authParamAUTN->value; - if (USE_SQN_HACK) - { - auto ak = calculateMilenage(OctetString::FromSpare(6), rand, false).ak; - m_usim->m_sqn = OctetString::Xor(autn.subCopy(0, 6), ak); - } - auto milenage = calculateMilenage(m_usim->m_sqn, rand, false); auto &res = milenage.res; auto &ck = milenage.ck; @@ -441,10 +435,8 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString } // Verify that the received sequence number SQN is in the correct range - if (!checkSqn(receivedSQN)) - { + if (!m_usim->checkSqn(receivedSQN)) return EAutnValidationRes::SYNCHRONISATION_FAILURE; - } // Check MAC if (receivedMAC != mac) @@ -457,14 +449,6 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString return EAutnValidationRes::OK; } -bool NasMm::checkSqn(const OctetString &sqn) -{ - // TODO: - // Verify the freshness of sequence numbers to determine whether the specified sequence number is - // in the correct range and acceptable by the USIM. See 3GPP TS 33.102, Annex C.2. - return true; -} - crypto::milenage::Milenage NasMm::calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf) { OctetString amf = dummyAmf ? OctetString::FromSpare(2) : m_base->config->amf.copy(); diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index 7d0ce291b..fa0e316e6 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -115,7 +115,6 @@ class NasMm void receiveEapFailureMessage(const eap::Eap &eap); void receiveEapResponseMessage(const eap::Eap &eap); EAutnValidationRes validateAutn(const OctetString &ak, const OctetString &mac, const OctetString &autn); - bool checkSqn(const OctetString &sqn); crypto::milenage::Milenage calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf); private: /* Security */ diff --git a/src/ue/nas/usim.cpp b/src/ue/nas/usim.cpp index 80316df7c..f08e4b3fc 100644 --- a/src/ue/nas/usim.cpp +++ b/src/ue/nas/usim.cpp @@ -33,4 +33,10 @@ void Usim::invalidate() m_isValid = false; } +bool Usim::checkSqn(const OctetString &sqn) +{ + // TODO + return false; +} + } // namespace nr::ue diff --git a/src/ue/nas/usim.hpp b/src/ue/nas/usim.hpp index 86d31ce1f..1375b7766 100644 --- a/src/ue/nas/usim.hpp +++ b/src/ue/nas/usim.hpp @@ -46,7 +46,6 @@ class Usim // Security related std::unique_ptr m_currentNsCtx{}; std::unique_ptr m_nonCurrentNsCtx{}; - OctetString m_sqn{}; OctetString m_rand{}; OctetString m_res{}; OctetString m_resStar{}; @@ -68,10 +67,16 @@ class Usim // eCall related bool m_isECallOnly{}; + // SQN management + OctetString m_sqn{}; + public: void initialize(bool hasSupi, const UeConfig::Initials &initials); + bool isValid(); void invalidate(); + + bool checkSqn(const OctetString &sqn); }; } // namespace nr::ue \ No newline at end of file From da1c6910c3dedcf2f3aed044b061c2a4596e7939 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 15:46:19 +0300 Subject: [PATCH 35/56] USIM refactor --- src/ue/nas/mm/base.cpp | 2 +- src/ue/nas/mm/mm.hpp | 2 +- src/ue/nas/task.hpp | 2 +- src/ue/nas/{ => usim}/usim.cpp | 0 src/ue/nas/{ => usim}/usim.hpp | 0 5 files changed, 3 insertions(+), 3 deletions(-) rename src/ue/nas/{ => usim}/usim.cpp (100%) rename src/ue/nas/{ => usim}/usim.hpp (100%) diff --git a/src/ue/nas/mm/base.cpp b/src/ue/nas/mm/base.cpp index a797f7c66..6580f3445 100644 --- a/src/ue/nas/mm/base.cpp +++ b/src/ue/nas/mm/base.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index fa0e316e6..a719fa4ec 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/ue/nas/task.hpp b/src/ue/nas/task.hpp index eb8dad9c4..285a2ef29 100644 --- a/src/ue/nas/task.hpp +++ b/src/ue/nas/task.hpp @@ -8,7 +8,7 @@ #pragma once -#include "usim.hpp" +#include #include #include #include diff --git a/src/ue/nas/usim.cpp b/src/ue/nas/usim/usim.cpp similarity index 100% rename from src/ue/nas/usim.cpp rename to src/ue/nas/usim/usim.cpp diff --git a/src/ue/nas/usim.hpp b/src/ue/nas/usim/usim.hpp similarity index 100% rename from src/ue/nas/usim.hpp rename to src/ue/nas/usim/usim.hpp From 9a36d6949868e57baf0eadb13312a44c9af44f79 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 17:32:42 +0300 Subject: [PATCH 36/56] USIM refactor --- src/ue/nas/mm/auth.cpp | 18 ++++----- src/ue/nas/usim/sqn_mng.cpp | 75 +++++++++++++++++++++++++++++++++++++ src/ue/nas/usim/sqn_mng.hpp | 44 ++++++++++++++++++++++ src/ue/nas/usim/usim.cpp | 8 +--- src/ue/nas/usim/usim.hpp | 11 +++--- 5 files changed, 134 insertions(+), 22 deletions(-) create mode 100644 src/ue/nas/usim/sqn_mng.cpp create mode 100644 src/ue/nas/usim/sqn_mng.hpp diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 5a90e7c64..38735651a 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -63,20 +63,20 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms // Log.warning(Tag.CONFIG, "USE_SQN_HACK: %s", USE_SQN_HACK); } - if (USE_SQN_HACK) + /*if (USE_SQN_HACK) { auto ak = calculateMilenage(OctetString::FromSpare(6), receivedRand, false).ak; m_usim->m_sqn = OctetString::Xor(receivedAutn.subCopy(0, 6), ak); - } + }*/ - auto milenage = calculateMilenage(m_usim->m_sqn, receivedRand, false); + auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), receivedRand, false); auto &res = milenage.res; auto &ck = milenage.ck; auto &ik = milenage.ik; auto &milenageAk = milenage.ak; auto &milenageMac = milenage.mac_a; - auto sqnXorAk = OctetString::Xor(m_usim->m_sqn, milenageAk); + auto sqnXorAk = OctetString::Xor(m_usim->m_sqnMng->getSqn(), milenageAk); auto ckPrimeIkPrime = keys::CalculateCkPrimeIkPrime(ck, ik, keys::ConstructServingNetworkName(*m_usim->m_currentPlmn), sqnXorAk); auto &ckPrime = ckPrimeIkPrime.first; @@ -289,14 +289,14 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto &rand = msg.authParamRAND->value; auto &autn = msg.authParamAUTN->value; - auto milenage = calculateMilenage(m_usim->m_sqn, rand, false); + auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, false); auto &res = milenage.res; auto &ck = milenage.ck; auto &ik = milenage.ik; auto ckIk = OctetString::Concat(ck, ik); auto &milenageAk = milenage.ak; auto &milenageMac = milenage.mac_a; - auto sqnXorAk = OctetString::Xor(m_usim->m_sqn, milenageAk); + auto sqnXorAk = OctetString::Xor(m_usim->m_sqnMng->getSqn(), milenageAk); auto snn = keys::ConstructServingNetworkName(*m_usim->m_currentPlmn); auto autnCheck = validateAutn(milenageAk, milenageMac, autn); @@ -329,8 +329,8 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) { - auto milenageForSync = calculateMilenage(m_usim->m_sqn, rand, true); - auto auts = keys::CalculateAuts(m_usim->m_sqn, milenageForSync.ak_r, milenageForSync.mac_s); + auto milenageForSync = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, true); + auto auts = keys::CalculateAuts(m_usim->m_sqnMng->getSqn(), milenageForSync.ak_r, milenageForSync.mac_s); sendFailure(nas::EMmCause::SYNCH_FAILURE, std::move(auts)); } else @@ -435,7 +435,7 @@ EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString } // Verify that the received sequence number SQN is in the correct range - if (!m_usim->checkSqn(receivedSQN)) + if (!m_usim->m_sqnMng->checkSqn(receivedSQN)) return EAutnValidationRes::SYNCHRONISATION_FAILURE; // Check MAC diff --git a/src/ue/nas/usim/sqn_mng.cpp b/src/ue/nas/usim/sqn_mng.cpp new file mode 100644 index 000000000..5582dc555 --- /dev/null +++ b/src/ue/nas/usim/sqn_mng.cpp @@ -0,0 +1,75 @@ +// +// This file is a part of UERANSIM open source project. +// Copyright (c) 2021 ALİ GÜNGÖR. +// +// The software and all associated files are licensed under GPL-3.0 +// and subject to the terms and conditions defined in LICENSE file. +// + +#include "sqn_mng.hpp" + +#include + +namespace nr::ue +{ + +SqnManager::SqnManager(uint64_t indBitLen, uint64_t wrappingDelta, uint64_t limit) + : m_indBitLen{indBitLen}, m_wrappingDelta{wrappingDelta}, m_limit{limit}, m_sqnArr(1ull << m_indBitLen) +{ + if (m_indBitLen < 2 || m_indBitLen > 16) + throw std::runtime_error("bad indBitLen"); +} + +uint64_t SqnManager::getSeqFromSqn(uint64_t sqn) const +{ + sqn &= ~((1ull << m_indBitLen) - 1ull); + sqn >>= m_indBitLen; + sqn &= (1ull << 48ull) - 1ull; + return sqn; +} + +uint64_t SqnManager::getIndFromSqn(uint64_t sqn) const +{ + return sqn & ((1ull << m_indBitLen) - 1ull); +} + +uint64_t SqnManager::getSeqMs() const +{ + return getSeqFromSqn(getSqnUL()); +} + +uint64_t SqnManager::getSqnUL() const +{ + return *std::max_element(m_sqnArr.begin(), m_sqnArr.end()); +} + +bool SqnManager::checkSqn(uint64_t sqn) +{ + uint64_t seq = getSeqFromSqn(sqn); + uint64_t ind = getIndFromSqn(sqn); + + if (seq - getSeqMs() > m_wrappingDelta) + return false; + if (getSeqMs() - seq >= m_limit) + return false; + if (seq <= getSeqFromSqn(m_sqnArr[ind])) + return false; + + m_sqnArr[ind] = sqn; + return true; +} + +bool SqnManager::checkSqn(const OctetString &sqn) +{ + OctetString str; + str.appendOctet2(0); + str.append(sqn); + return checkSqn(str.get8UL(0)); +} + +OctetString SqnManager::getSqn() const +{ + return OctetString::FromOctet8(getSqnUL()).subCopy(2); +} + +} // namespace nr::ue diff --git a/src/ue/nas/usim/sqn_mng.hpp b/src/ue/nas/usim/sqn_mng.hpp new file mode 100644 index 000000000..e4169726f --- /dev/null +++ b/src/ue/nas/usim/sqn_mng.hpp @@ -0,0 +1,44 @@ +// +// This file is a part of UERANSIM open source project. +// Copyright (c) 2021 ALİ GÜNGÖR. +// +// The software and all associated files are licensed under GPL-3.0 +// and subject to the terms and conditions defined in LICENSE file. +// + +#pragma once + +#include +#include +#include + +#include + +namespace nr::ue +{ + +class SqnManager +{ + private: + uint64_t m_indBitLen; + uint64_t m_wrappingDelta; + uint64_t m_limit; + + std::vector m_sqnArr; + + public: + SqnManager(uint64_t indBitLen, uint64_t wrappingDelta, uint64_t limit); + + private: + [[nodiscard]] uint64_t getSeqFromSqn(uint64_t sqn) const; + [[nodiscard]] uint64_t getIndFromSqn(uint64_t sqn) const; + [[nodiscard]] uint64_t getSeqMs() const; + + public: + [[nodiscard]] uint64_t getSqnUL() const; + [[nodiscard]] OctetString getSqn() const; + bool checkSqn(uint64_t sqn); + bool checkSqn(const OctetString &sqn); +}; + +} // namespace nr::ue diff --git a/src/ue/nas/usim/usim.cpp b/src/ue/nas/usim/usim.cpp index f08e4b3fc..b3b42d0ed 100644 --- a/src/ue/nas/usim/usim.cpp +++ b/src/ue/nas/usim/usim.cpp @@ -20,7 +20,7 @@ void ue::Usim::initialize(bool hasSupi, const UeConfig::Initials &initials) m_defConfiguredNssai = initials.defaultConfiguredNssai; m_configuredNssai = initials.configuredNssai; - m_sqn = OctetString::FromSpare(6); + m_sqnMng = std::make_unique(5ull, 1ull << 28ull, ~0ull); } bool Usim::isValid() @@ -33,10 +33,4 @@ void Usim::invalidate() m_isValid = false; } -bool Usim::checkSqn(const OctetString &sqn) -{ - // TODO - return false; -} - } // namespace nr::ue diff --git a/src/ue/nas/usim/usim.hpp b/src/ue/nas/usim/usim.hpp index 1375b7766..5333a4e71 100644 --- a/src/ue/nas/usim/usim.hpp +++ b/src/ue/nas/usim/usim.hpp @@ -8,9 +8,12 @@ #pragma once -#include +#include "sqn_mng.hpp" + #include #include + +#include #include #include #include @@ -49,6 +52,7 @@ class Usim OctetString m_rand{}; OctetString m_res{}; OctetString m_resStar{}; + std::unique_ptr m_sqnMng{}; // NSSAI related NetworkSlice m_defConfiguredNssai{}; @@ -67,16 +71,11 @@ class Usim // eCall related bool m_isECallOnly{}; - // SQN management - OctetString m_sqn{}; - public: void initialize(bool hasSupi, const UeConfig::Initials &initials); bool isValid(); void invalidate(); - - bool checkSqn(const OctetString &sqn); }; } // namespace nr::ue \ No newline at end of file From 611a2ea4142083df615a12bce18e8fcf81dd05b7 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 17:47:34 +0300 Subject: [PATCH 37/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 48 +++++++++++++++++++++--------------------- src/ue/nas/mm/mm.hpp | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 38735651a..768a9cfef 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -74,7 +74,6 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms auto &ck = milenage.ck; auto &ik = milenage.ik; auto &milenageAk = milenage.ak; - auto &milenageMac = milenage.mac_a; auto sqnXorAk = OctetString::Xor(m_usim->m_sqnMng->getSqn(), milenageAk); auto ckPrimeIkPrime = @@ -123,7 +122,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms } // Control received AUTN - auto autnCheck = validateAutn(milenageAk, milenageMac, receivedAutn); + auto autnCheck = validateAutn(receivedRand, receivedAutn); if (autnCheck != EAutnValidationRes::OK) { eap::EapAkaPrime *eapResponse = nullptr; @@ -289,30 +288,26 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto &rand = msg.authParamRAND->value; auto &autn = msg.authParamAUTN->value; - auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, false); - auto &res = milenage.res; - auto &ck = milenage.ck; - auto &ik = milenage.ik; - auto ckIk = OctetString::Concat(ck, ik); - auto &milenageAk = milenage.ak; - auto &milenageMac = milenage.mac_a; - auto sqnXorAk = OctetString::Xor(m_usim->m_sqnMng->getSqn(), milenageAk); - auto snn = keys::ConstructServingNetworkName(*m_usim->m_currentPlmn); - - auto autnCheck = validateAutn(milenageAk, milenageMac, autn); + auto autnCheck = validateAutn(rand, autn); if (autnCheck == EAutnValidationRes::OK) { + // Calculate milenage + auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, false); + auto ckIk = OctetString::Concat(milenage.ck, milenage.ik); + auto sqnXorAk = OctetString::Xor(m_usim->m_sqnMng->getSqn(), milenage.ak); + auto snn = keys::ConstructServingNetworkName(*m_usim->m_currentPlmn); + // Store the relevant parameters m_usim->m_rand = rand.copy(); - m_usim->m_resStar = keys::CalculateResStar(ckIk, snn, rand, res); - m_usim->m_res = std::move(res); + m_usim->m_resStar = keys::CalculateResStar(ckIk, snn, rand, milenage.res); + m_usim->m_res = milenage.res.copy(); // Create new partial native NAS security context and continue with key derivation m_usim->m_nonCurrentNsCtx = std::make_unique(); m_usim->m_nonCurrentNsCtx->tsc = msg.ngKSI.tsc; m_usim->m_nonCurrentNsCtx->ngKsi = msg.ngKSI.ksi; - m_usim->m_nonCurrentNsCtx->keys.kAusf = keys::CalculateKAusfFor5gAka(ck, ik, snn, sqnXorAk); + m_usim->m_nonCurrentNsCtx->keys.kAusf = keys::CalculateKAusfFor5gAka(milenage.ck, milenage.ik, snn, sqnXorAk); m_usim->m_nonCurrentNsCtx->keys.abba = msg.abba.rawData.copy(); keys::DeriveKeysSeafAmf(*m_base->config, *m_usim->m_currentPlmn, *m_usim->m_nonCurrentNsCtx); @@ -329,8 +324,8 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) { - auto milenageForSync = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, true); - auto auts = keys::CalculateAuts(m_usim->m_sqnMng->getSqn(), milenageForSync.ak_r, milenageForSync.mac_s); + auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, true); + auto auts = keys::CalculateAuts(m_usim->m_sqnMng->getSqn(), milenage.ak_r, milenage.mac_s); sendFailure(nas::EMmCause::SYNCH_FAILURE, std::move(auts)); } else @@ -418,30 +413,35 @@ void NasMm::receiveEapResponseMessage(const eap::Eap &eap) } } -EAutnValidationRes NasMm::validateAutn(const OctetString &ak, const OctetString &mac, const OctetString &autn) +EAutnValidationRes NasMm::validateAutn(const OctetString &rand, const OctetString &autn) { // Decode AUTN OctetString receivedSQNxorAK = autn.subCopy(0, 6); - OctetString receivedSQN = OctetString::Xor(receivedSQNxorAK, ak); OctetString receivedAMF = autn.subCopy(6, 2); OctetString receivedMAC = autn.subCopy(8, 8); - // TS 33.501: An ME accessing 5G shall check during authentication that the "separation bit" in the AMF field - // of AUTN is set to 1. The "separation bit" is bit 0 of the AMF field of AUTN. + // Check the separation bit if (receivedAMF.get(0).bit(7) != 1) { m_logger->err("AUTN validation SEP-BIT failure. expected: 1, received: 0"); return EAutnValidationRes::AMF_SEPARATION_BIT_FAILURE; } + // Derive AK and MAC + auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, false); + OctetString receivedSQN = OctetString::Xor(receivedSQNxorAK, milenage.ak); + // Verify that the received sequence number SQN is in the correct range if (!m_usim->m_sqnMng->checkSqn(receivedSQN)) return EAutnValidationRes::SYNCHRONISATION_FAILURE; + // Re-execute the milenage calculation (if case of sqn is changed with the received value) + milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, false); + // Check MAC - if (receivedMAC != mac) + if (receivedMAC != milenage.mac_a) { - m_logger->err("AUTN validation MAC mismatch. expected [%s] received [%s]", mac.toHexString().c_str(), + m_logger->err("AUTN validation MAC mismatch. expected [%s] received [%s]", milenage.mac_a.toHexString().c_str(), receivedMAC.toHexString().c_str()); return EAutnValidationRes::MAC_FAILURE; } diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index a719fa4ec..15d6773ee 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -114,7 +114,7 @@ class NasMm void receiveEapSuccessMessage(const eap::Eap &eap); void receiveEapFailureMessage(const eap::Eap &eap); void receiveEapResponseMessage(const eap::Eap &eap); - EAutnValidationRes validateAutn(const OctetString &ak, const OctetString &mac, const OctetString &autn); + EAutnValidationRes validateAutn(const OctetString &rand, const OctetString &autn); crypto::milenage::Milenage calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf); private: /* Security */ From eca3b993e8be3dbbc16f051d44f7563bc667c531 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 17:54:07 +0300 Subject: [PATCH 38/56] UE authentication procedure improvements --- src/ue/nas/usim/sqn_mng.cpp | 6 ++---- src/ue/nas/usim/sqn_mng.hpp | 3 +-- src/ue/nas/usim/usim.cpp | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/ue/nas/usim/sqn_mng.cpp b/src/ue/nas/usim/sqn_mng.cpp index 5582dc555..087968505 100644 --- a/src/ue/nas/usim/sqn_mng.cpp +++ b/src/ue/nas/usim/sqn_mng.cpp @@ -13,8 +13,8 @@ namespace nr::ue { -SqnManager::SqnManager(uint64_t indBitLen, uint64_t wrappingDelta, uint64_t limit) - : m_indBitLen{indBitLen}, m_wrappingDelta{wrappingDelta}, m_limit{limit}, m_sqnArr(1ull << m_indBitLen) +SqnManager::SqnManager(uint64_t indBitLen, uint64_t wrappingDelta) + : m_indBitLen{indBitLen}, m_wrappingDelta{wrappingDelta}, m_sqnArr(1ull << m_indBitLen) { if (m_indBitLen < 2 || m_indBitLen > 16) throw std::runtime_error("bad indBitLen"); @@ -50,8 +50,6 @@ bool SqnManager::checkSqn(uint64_t sqn) if (seq - getSeqMs() > m_wrappingDelta) return false; - if (getSeqMs() - seq >= m_limit) - return false; if (seq <= getSeqFromSqn(m_sqnArr[ind])) return false; diff --git a/src/ue/nas/usim/sqn_mng.hpp b/src/ue/nas/usim/sqn_mng.hpp index e4169726f..c474f49d9 100644 --- a/src/ue/nas/usim/sqn_mng.hpp +++ b/src/ue/nas/usim/sqn_mng.hpp @@ -22,12 +22,11 @@ class SqnManager private: uint64_t m_indBitLen; uint64_t m_wrappingDelta; - uint64_t m_limit; std::vector m_sqnArr; public: - SqnManager(uint64_t indBitLen, uint64_t wrappingDelta, uint64_t limit); + SqnManager(uint64_t indBitLen, uint64_t wrappingDelta); private: [[nodiscard]] uint64_t getSeqFromSqn(uint64_t sqn) const; diff --git a/src/ue/nas/usim/usim.cpp b/src/ue/nas/usim/usim.cpp index b3b42d0ed..26fb7af5e 100644 --- a/src/ue/nas/usim/usim.cpp +++ b/src/ue/nas/usim/usim.cpp @@ -20,7 +20,7 @@ void ue::Usim::initialize(bool hasSupi, const UeConfig::Initials &initials) m_defConfiguredNssai = initials.defaultConfiguredNssai; m_configuredNssai = initials.configuredNssai; - m_sqnMng = std::make_unique(5ull, 1ull << 28ull, ~0ull); + m_sqnMng = std::make_unique(5ull, 1ull << 28ull); } bool Usim::isValid() From 216e3f0b6141f4b11a5583ffaccdb5de373a0453 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:04:55 +0300 Subject: [PATCH 39/56] UE authentication procedure improvements --- src/ue/nas/usim/sqn_mng.cpp | 16 +++++++++++++--- src/ue/nas/usim/sqn_mng.hpp | 5 +++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/ue/nas/usim/sqn_mng.cpp b/src/ue/nas/usim/sqn_mng.cpp index 087968505..294dc1cff 100644 --- a/src/ue/nas/usim/sqn_mng.cpp +++ b/src/ue/nas/usim/sqn_mng.cpp @@ -18,6 +18,8 @@ SqnManager::SqnManager(uint64_t indBitLen, uint64_t wrappingDelta) { if (m_indBitLen < 2 || m_indBitLen > 16) throw std::runtime_error("bad indBitLen"); + + m_sqnArr[0] = 0xFFFFFFFFFFFFULL; } uint64_t SqnManager::getSeqFromSqn(uint64_t sqn) const @@ -35,10 +37,15 @@ uint64_t SqnManager::getIndFromSqn(uint64_t sqn) const uint64_t SqnManager::getSeqMs() const { - return getSeqFromSqn(getSqnUL()); + return getSeqFromSqn(getSqnValue()); +} + +uint64_t &SqnManager::getSqnRef() +{ + return *std::max_element(m_sqnArr.begin(), m_sqnArr.end()); } -uint64_t SqnManager::getSqnUL() const +uint64_t SqnManager::getSqnValue() const { return *std::max_element(m_sqnArr.begin(), m_sqnArr.end()); } @@ -49,7 +56,10 @@ bool SqnManager::checkSqn(uint64_t sqn) uint64_t ind = getIndFromSqn(sqn); if (seq - getSeqMs() > m_wrappingDelta) + { + getSqnRef() -= m_wrappingDelta; return false; + } if (seq <= getSeqFromSqn(m_sqnArr[ind])) return false; @@ -67,7 +77,7 @@ bool SqnManager::checkSqn(const OctetString &sqn) OctetString SqnManager::getSqn() const { - return OctetString::FromOctet8(getSqnUL()).subCopy(2); + return OctetString::FromOctet8(getSqnValue()).subCopy(2); } } // namespace nr::ue diff --git a/src/ue/nas/usim/sqn_mng.hpp b/src/ue/nas/usim/sqn_mng.hpp index c474f49d9..c3770ec28 100644 --- a/src/ue/nas/usim/sqn_mng.hpp +++ b/src/ue/nas/usim/sqn_mng.hpp @@ -32,11 +32,12 @@ class SqnManager [[nodiscard]] uint64_t getSeqFromSqn(uint64_t sqn) const; [[nodiscard]] uint64_t getIndFromSqn(uint64_t sqn) const; [[nodiscard]] uint64_t getSeqMs() const; + [[nodiscard]] uint64_t &getSqnRef(); + [[nodiscard]] uint64_t getSqnValue() const; + bool checkSqn(uint64_t sqn); public: - [[nodiscard]] uint64_t getSqnUL() const; [[nodiscard]] OctetString getSqn() const; - bool checkSqn(uint64_t sqn); bool checkSqn(const OctetString &sqn); }; From 684c093294c7c388a364b1158a586bf1db1b94cf Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:05:18 +0300 Subject: [PATCH 40/56] UE authentication procedure improvements --- src/ue/nas/usim/sqn_mng.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ue/nas/usim/sqn_mng.cpp b/src/ue/nas/usim/sqn_mng.cpp index 294dc1cff..eff99f873 100644 --- a/src/ue/nas/usim/sqn_mng.cpp +++ b/src/ue/nas/usim/sqn_mng.cpp @@ -18,8 +18,6 @@ SqnManager::SqnManager(uint64_t indBitLen, uint64_t wrappingDelta) { if (m_indBitLen < 2 || m_indBitLen > 16) throw std::runtime_error("bad indBitLen"); - - m_sqnArr[0] = 0xFFFFFFFFFFFFULL; } uint64_t SqnManager::getSeqFromSqn(uint64_t sqn) const From 82828c1ef2c5160e475138f6942525925d72749c Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:20:21 +0300 Subject: [PATCH 41/56] UE authentication procedure improvements --- src/ue/nas/usim/sqn_mng.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ue/nas/usim/sqn_mng.cpp b/src/ue/nas/usim/sqn_mng.cpp index eff99f873..f85e20220 100644 --- a/src/ue/nas/usim/sqn_mng.cpp +++ b/src/ue/nas/usim/sqn_mng.cpp @@ -54,10 +54,7 @@ bool SqnManager::checkSqn(uint64_t sqn) uint64_t ind = getIndFromSqn(sqn); if (seq - getSeqMs() > m_wrappingDelta) - { - getSqnRef() -= m_wrappingDelta; return false; - } if (seq <= getSeqFromSqn(m_sqnArr[ind])) return false; From 68a4fbd2a39a7462205301413d1dc8b2229a532e Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:26:32 +0300 Subject: [PATCH 42/56] UE authentication procedure improvements --- src/ue/nas/usim/sqn_mng.cpp | 11 +++-------- src/ue/nas/usim/sqn_mng.hpp | 3 +-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/ue/nas/usim/sqn_mng.cpp b/src/ue/nas/usim/sqn_mng.cpp index f85e20220..5c8e9f732 100644 --- a/src/ue/nas/usim/sqn_mng.cpp +++ b/src/ue/nas/usim/sqn_mng.cpp @@ -35,15 +35,10 @@ uint64_t SqnManager::getIndFromSqn(uint64_t sqn) const uint64_t SqnManager::getSeqMs() const { - return getSeqFromSqn(getSqnValue()); + return getSeqFromSqn(getSqnMs()); } -uint64_t &SqnManager::getSqnRef() -{ - return *std::max_element(m_sqnArr.begin(), m_sqnArr.end()); -} - -uint64_t SqnManager::getSqnValue() const +uint64_t SqnManager::getSqnMs() const { return *std::max_element(m_sqnArr.begin(), m_sqnArr.end()); } @@ -72,7 +67,7 @@ bool SqnManager::checkSqn(const OctetString &sqn) OctetString SqnManager::getSqn() const { - return OctetString::FromOctet8(getSqnValue()).subCopy(2); + return OctetString::FromOctet8(getSqnMs()).subCopy(2); } } // namespace nr::ue diff --git a/src/ue/nas/usim/sqn_mng.hpp b/src/ue/nas/usim/sqn_mng.hpp index c3770ec28..ab981dc24 100644 --- a/src/ue/nas/usim/sqn_mng.hpp +++ b/src/ue/nas/usim/sqn_mng.hpp @@ -32,8 +32,7 @@ class SqnManager [[nodiscard]] uint64_t getSeqFromSqn(uint64_t sqn) const; [[nodiscard]] uint64_t getIndFromSqn(uint64_t sqn) const; [[nodiscard]] uint64_t getSeqMs() const; - [[nodiscard]] uint64_t &getSqnRef(); - [[nodiscard]] uint64_t getSqnValue() const; + [[nodiscard]] uint64_t getSqnMs() const; bool checkSqn(uint64_t sqn); public: From 9239919251f6a302168e83363ac80b3f43b47890 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:30:46 +0300 Subject: [PATCH 43/56] DEREGISTRATION_ACCEPT_UE_ORIGINATING is accepted without integrity --- src/ue/nas/mm/transport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ue/nas/mm/transport.cpp b/src/ue/nas/mm/transport.cpp index 016421cb9..48ecd5a1f 100644 --- a/src/ue/nas/mm/transport.cpp +++ b/src/ue/nas/mm/transport.cpp @@ -30,7 +30,7 @@ static bool IsAcceptedWithoutIntegrity(const nas::PlainMmMessage &msg) return msgType == nas::EMessageType::IDENTITY_REQUEST || msgType == nas::EMessageType::AUTHENTICATION_REQUEST || msgType == nas::EMessageType::AUTHENTICATION_RESULT || msgType == nas::EMessageType::AUTHENTICATION_REJECT || msgType == nas::EMessageType::REGISTRATION_REJECT || - msgType == nas::EMessageType::DEREGISTRATION_ACCEPT_UE_TERMINATED || + msgType == nas::EMessageType::DEREGISTRATION_ACCEPT_UE_ORIGINATING || msgType == nas::EMessageType::SERVICE_REJECT; } From 912dd5c048478d59685b4e6593a704202269f212 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:31:30 +0300 Subject: [PATCH 44/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 768a9cfef..e394c4926 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -224,6 +224,8 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto sendFailure = [this](nas::EMmCause cause, std::optional &&auts = std::nullopt) { if (cause != nas::EMmCause::SYNCH_FAILURE) m_logger->err("Sending Authentication Failure with cause [%s]", nas::utils::EnumToString(cause)); + else + m_logger->debug("Sending Authentication Failure deu to SQN out of range"); // Clear parameters stored in volatile memory of ME m_usim->m_rand = {}; From 9ec69ec676a5b1f0215d98b620dd713832e1e3f7 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:31:39 +0300 Subject: [PATCH 45/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index e394c4926..07bdccb74 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -225,7 +225,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & if (cause != nas::EMmCause::SYNCH_FAILURE) m_logger->err("Sending Authentication Failure with cause [%s]", nas::utils::EnumToString(cause)); else - m_logger->debug("Sending Authentication Failure deu to SQN out of range"); + m_logger->debug("Sending Authentication Failure due to SQN out of range"); // Clear parameters stored in volatile memory of ME m_usim->m_rand = {}; From b04d7b869567e4ca905cac782aa99e73350315df Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:41:26 +0300 Subject: [PATCH 46/56] UE authentication procedure improvements --- src/ue/nas/mm/auth.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 07bdccb74..4d2083f1f 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -290,7 +290,16 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & auto &rand = msg.authParamRAND->value; auto &autn = msg.authParamAUTN->value; - auto autnCheck = validateAutn(rand, autn); + EAutnValidationRes autnCheck = EAutnValidationRes::OK; + + // If the received RAND is same with store stored RAND, bypass AUTN validation + // NOTE: Not completely sure if this is correct and the spec meant this. But in worst case, synchronisation failure + // happens, and hopefully that can be restored with the normal resynchronization procedure. + if (m_usim->m_rand != rand) + { + autnCheck = validateAutn(rand, autn); + m_timers->t3516.start(); + } if (autnCheck == EAutnValidationRes::OK) { From c2122e03f1b008e79f9cf2c2f72fcec0e51266aa Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:44:05 +0300 Subject: [PATCH 47/56] T3516 handling --- src/ue/nas/mm/auth.cpp | 7 ++----- src/ue/nas/mm/timer.cpp | 5 +++++ src/ue/nas/usim/usim.hpp | 1 - 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 4d2083f1f..4b7d9c11e 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -187,7 +187,6 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms m_usim->m_nonCurrentNsCtx->tsc = msg.ngKSI.tsc; m_usim->m_nonCurrentNsCtx->ngKsi = msg.ngKSI.ksi; m_usim->m_rand = std::move(receivedRand); - m_usim->m_res = std::move(res); m_usim->m_resStar = {}; m_usim->m_nonCurrentNsCtx->keys.kAusf = std::move(kAusf); m_usim->m_nonCurrentNsCtx->keys.abba = msg.abba.rawData.copy(); @@ -201,7 +200,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms { auto *akaPrimeResponse = new eap::EapAkaPrime(eap::ECode::RESPONSE, receivedEap.id, eap::ESubType::AKA_CHALLENGE); - akaPrimeResponse->attributes.putRes(m_usim->m_res); + akaPrimeResponse->attributes.putRes(res); akaPrimeResponse->attributes.putMac(OctetString::FromSpare(16)); // Dummy mac for now akaPrimeResponse->attributes.putKdf(1); @@ -227,9 +226,8 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & else m_logger->debug("Sending Authentication Failure due to SQN out of range"); - // Clear parameters stored in volatile memory of ME + // Clear RAND and RES* stored in volatile memory m_usim->m_rand = {}; - m_usim->m_res = {}; m_usim->m_resStar = {}; // Stop T3516 if running @@ -312,7 +310,6 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & // Store the relevant parameters m_usim->m_rand = rand.copy(); m_usim->m_resStar = keys::CalculateResStar(ckIk, snn, rand, milenage.res); - m_usim->m_res = milenage.res.copy(); // Create new partial native NAS security context and continue with key derivation m_usim->m_nonCurrentNsCtx = std::make_unique(); diff --git a/src/ue/nas/mm/timer.cpp b/src/ue/nas/mm/timer.cpp index d2f7dd31f..2c63227d9 100644 --- a/src/ue/nas/mm/timer.cpp +++ b/src/ue/nas/mm/timer.cpp @@ -85,6 +85,11 @@ void NasMm::onTimerExpire(nas::NasTimer &timer) } break; } + case 3516: { + m_usim->m_rand = {}; + m_usim->m_resStar = {}; + break; + } case 3517: { if (m_mmState == EMmState::MM_SERVICE_REQUEST_INITIATED) { diff --git a/src/ue/nas/usim/usim.hpp b/src/ue/nas/usim/usim.hpp index 5333a4e71..b821dd011 100644 --- a/src/ue/nas/usim/usim.hpp +++ b/src/ue/nas/usim/usim.hpp @@ -50,7 +50,6 @@ class Usim std::unique_ptr m_currentNsCtx{}; std::unique_ptr m_nonCurrentNsCtx{}; OctetString m_rand{}; - OctetString m_res{}; OctetString m_resStar{}; std::unique_ptr m_sqnMng{}; From f1e28191c14602d14c7852ae8819d254c1ce6250 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 18:52:25 +0300 Subject: [PATCH 48/56] T3516 handling --- src/ue/nas/mm/auth.cpp | 5 +++++ src/ue/nas/mm/base.cpp | 15 +++++++++++++++ src/ue/nas/mm/register.cpp | 10 ++++++++++ src/ue/nas/mm/security.cpp | 5 +++++ src/ue/nas/mm/service.cpp | 5 +++++ 5 files changed, 40 insertions(+) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 4b7d9c11e..1382850bc 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -371,6 +371,11 @@ void NasMm::receiveAuthenticationReject(const nas::AuthenticationReject &msg) { m_logger->err("Authentication Reject received."); + // The RAND and RES* values stored in the ME shall be deleted and timer T3516, if running, shall be stopped + m_usim->m_rand = {}; + m_usim->m_resStar = {}; + m_timers->t3516.stop(); + if (msg.eapMessage.has_value() && msg.eapMessage->eap->code != eap::ECode::FAILURE) { m_logger->warn("Network sent EAP with inconvenient type in AuthenticationReject, ignoring EAP IE."); diff --git a/src/ue/nas/mm/base.cpp b/src/ue/nas/mm/base.cpp index 6580f3445..7f06ef975 100644 --- a/src/ue/nas/mm/base.cpp +++ b/src/ue/nas/mm/base.cpp @@ -232,6 +232,15 @@ void NasMm::onSwitchMmState(EMmState oldState, EMmState newState, EMmSubState ol m_usim->m_nonCurrentNsCtx = {}; } } + + // If the UE enters the 5GMM state 5GMM-DEREGISTERED or 5GMM-NULL, + // The RAND and RES* values stored in the ME shall be deleted and timer T3516, if running, shall be stopped + if (newState == EMmState::MM_DEREGISTERED || newState == EMmState::MM_NULL) + { + m_usim->m_rand = {}; + m_usim->m_resStar = {}; + m_timers->t3516.stop(); + } } void NasMm::onSwitchRmState(ERmState oldState, ERmState newState) @@ -278,6 +287,12 @@ void NasMm::onSwitchCmState(ECmState oldState, ECmState newState) nas::ESwitchOff::NORMAL_DE_REGISTRATION) switchMmState(EMmState::MM_DEREGISTERED, EMmSubState::MM_DEREGISTERED_NA); } + + // If the UE enters the 5GMM-IDLE, the RAND and RES* values stored + // in the ME shall be deleted and timer T3516, if running, shall be stopped + m_usim->m_rand = {}; + m_usim->m_resStar = {}; + m_timers->t3516.stop(); } } diff --git a/src/ue/nas/mm/register.cpp b/src/ue/nas/mm/register.cpp index 84977c429..443723fda 100644 --- a/src/ue/nas/mm/register.cpp +++ b/src/ue/nas/mm/register.cpp @@ -220,6 +220,11 @@ void NasMm::receiveRegistrationAccept(const nas::RegistrationAccept &msg) receiveInitialRegistrationAccept(msg); else receiveMobilityRegistrationAccept(msg); + + // The RAND and RES* values stored in the ME shall be deleted and timer T3516, if running, shall be stopped + m_usim->m_rand = {}; + m_usim->m_resStar = {}; + m_timers->t3516.stop(); } void NasMm::receiveInitialRegistrationAccept(const nas::RegistrationAccept &msg) @@ -451,6 +456,11 @@ void NasMm::receiveRegistrationReject(const nas::RegistrationReject &msg) receiveInitialRegistrationReject(msg); else receiveMobilityRegistrationReject(msg); + + // The RAND and RES* values stored in the ME shall be deleted and timer T3516, if running, shall be stopped + m_usim->m_rand = {}; + m_usim->m_resStar = {}; + m_timers->t3516.stop(); } void NasMm::receiveInitialRegistrationReject(const nas::RegistrationReject &msg) diff --git a/src/ue/nas/mm/security.cpp b/src/ue/nas/mm/security.cpp index 952179567..0a760919a 100644 --- a/src/ue/nas/mm/security.cpp +++ b/src/ue/nas/mm/security.cpp @@ -59,6 +59,11 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg) m_logger->err("Rejecting Security Mode Command with cause [%s]", nas::utils::EnumToString(cause)); }; + // The RAND and RES* values stored in the ME shall be deleted and timer T3516, if running, shall be stopped + m_usim->m_rand = {}; + m_usim->m_resStar = {}; + m_timers->t3516.stop(); + // ============================== Check the received ngKSI ============================== bool locallyDerived = false; diff --git a/src/ue/nas/mm/service.cpp b/src/ue/nas/mm/service.cpp index 683f90b7d..8947a9d7f 100644 --- a/src/ue/nas/mm/service.cpp +++ b/src/ue/nas/mm/service.cpp @@ -212,6 +212,11 @@ void NasMm::receiveServiceReject(const nas::ServiceReject &msg) m_serCounter = 0; m_timers->t3517.stop(); + // The RAND and RES* values stored in the ME shall be deleted and timer T3516, if running, shall be stopped + m_usim->m_rand = {}; + m_usim->m_resStar = {}; + m_timers->t3516.stop(); + auto cause = msg.mmCause.value; m_logger->err("Service Reject received with cause [%s]", nas::utils::EnumToString(cause)); From c81325d059f3ae87e927a21a8b01a0d42fcdfd1e Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 19:07:18 +0300 Subject: [PATCH 49/56] Authentication abnormal case handling --- src/ue/nas/mm/auth.cpp | 8 ++++++++ src/ue/nas/mm/mm.hpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 1382850bc..afe2824bb 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -24,6 +24,8 @@ void NasMm::receiveAuthenticationRequest(const nas::AuthenticationRequest &msg) return; } + m_timers->t3520.start(); + if (msg.eapMessage.has_value()) receiveAuthenticationRequestEap(msg); else @@ -325,9 +327,15 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & resp.authenticationResponseParameter = nas::IEAuthenticationResponseParameter{}; resp.authenticationResponseParameter->rawData = m_usim->m_resStar.copy(); sendNasMessage(resp); + + // 5.4.1.3.7, c) + restorePreviouslyStoppedAndSavedRetransmissionTimers(); } else if (autnCheck == EAutnValidationRes::MAC_FAILURE) { + stopAndSaveRetransmissionTimers(); + m_timers->t3520.start(); + sendFailure(nas::EMmCause::MAC_FAILURE); } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index 15d6773ee..b8bfc2093 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -167,6 +167,8 @@ class NasMm private: /* Timer */ void onTimerExpire(nas::NasTimer &timer); + void stopAndSaveRetransmissionTimers(); + void restorePreviouslyStoppedAndSavedRetransmissionTimers(); public: /* Interface */ From 6e23a56c26589845c3d8215c16802c66b8055222 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 19:14:28 +0300 Subject: [PATCH 50/56] Authentication abnormal case handling --- src/ue/nas/mm/auth.cpp | 10 +++++++--- src/ue/nas/mm/mm.hpp | 2 -- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index afe2824bb..69d153b1e 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -328,12 +328,16 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & resp.authenticationResponseParameter->rawData = m_usim->m_resStar.copy(); sendNasMessage(resp); - // 5.4.1.3.7, c) - restorePreviouslyStoppedAndSavedRetransmissionTimers(); + // 5.4.1.3.7, Item c) + // NOTE: Spec says UE shall start any retransmission timers previously stopped due to MAC failure + (void)0; } else if (autnCheck == EAutnValidationRes::MAC_FAILURE) { - stopAndSaveRetransmissionTimers(); + // 5.4.1.3.7, Item c) + // NOTE: Spec says UE shall stop any retransmission timers + (void)0; + m_timers->t3520.start(); sendFailure(nas::EMmCause::MAC_FAILURE); diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index b8bfc2093..15d6773ee 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -167,8 +167,6 @@ class NasMm private: /* Timer */ void onTimerExpire(nas::NasTimer &timer); - void stopAndSaveRetransmissionTimers(); - void restorePreviouslyStoppedAndSavedRetransmissionTimers(); public: /* Interface */ From 64374bad0af97d1bdfc865b1ddbbf8a20d2f3505 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 19:18:24 +0300 Subject: [PATCH 51/56] Authentication abnormal case handling --- src/ue/nas/mm/auth.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index 69d153b1e..f0c5c3558 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -46,8 +46,6 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms m_timers->t3521.stop(); }; - m_timers->t3520.stop(); - // Read EAP-AKA' request auto &receivedEap = (const eap::EapAkaPrime &)*msg.eapMessage->eap; auto receivedRand = receivedEap.attributes.getRand(); @@ -281,6 +279,8 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & if ((m_usim->m_currentNsCtx && m_usim->m_currentNsCtx->ngKsi == msg.ngKSI.ksi) || (m_usim->m_nonCurrentNsCtx && m_usim->m_nonCurrentNsCtx->ngKsi == msg.ngKSI.ksi)) { + m_timers->t3520.start(); + sendFailure(nas::EMmCause::NGKSI_ALREADY_IN_USE); return; } @@ -323,33 +323,32 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & keys::DeriveKeysSeafAmf(*m_base->config, *m_usim->m_currentPlmn, *m_usim->m_nonCurrentNsCtx); // Send response + m_timers->t3520.stop(); + nas::AuthenticationResponse resp; resp.authenticationResponseParameter = nas::IEAuthenticationResponseParameter{}; resp.authenticationResponseParameter->rawData = m_usim->m_resStar.copy(); - sendNasMessage(resp); - // 5.4.1.3.7, Item c) - // NOTE: Spec says UE shall start any retransmission timers previously stopped due to MAC failure - (void)0; + sendNasMessage(resp); } else if (autnCheck == EAutnValidationRes::MAC_FAILURE) { - // 5.4.1.3.7, Item c) - // NOTE: Spec says UE shall stop any retransmission timers - (void)0; - m_timers->t3520.start(); sendFailure(nas::EMmCause::MAC_FAILURE); } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) { + m_timers->t3520.start(); + auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, true); auto auts = keys::CalculateAuts(m_usim->m_sqnMng->getSqn(), milenage.ak_r, milenage.mac_s); sendFailure(nas::EMmCause::SYNCH_FAILURE, std::move(auts)); } else { + m_timers->t3520.start(); + // the other case, separation bit mismatched sendFailure(nas::EMmCause::NON_5G_AUTHENTICATION_UNACCEPTABLE); } From 6a9f533b9a19e747621a4b4393930e6a4ba6b377 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 19:26:00 +0300 Subject: [PATCH 52/56] Authentication abnormal case handling --- src/ue/nas/mm/auth.cpp | 8 ++++++++ src/ue/nas/mm/mm.hpp | 1 + 2 files changed, 9 insertions(+) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index f0c5c3558..bb08ce3fd 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -484,4 +484,12 @@ crypto::milenage::Milenage NasMm::calculateMilenage(const OctetString &sqn, cons return crypto::milenage::Calculate(opc, m_base->config->key, rand, sqn, amf); } +void NasMm::networkFailingTheAuth() +{ + m_logger->err("Network failing the authentication check"); + localReleaseConnection(); + + // TODO: treat the active cell as barred +} + } // namespace nr::ue \ No newline at end of file diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index 15d6773ee..8a5c0bd40 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -116,6 +116,7 @@ class NasMm void receiveEapResponseMessage(const eap::Eap &eap); EAutnValidationRes validateAutn(const OctetString &rand, const OctetString &autn); crypto::milenage::Milenage calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf); + void networkFailingTheAuth(); private: /* Security */ void receiveSecurityModeCommand(const nas::SecurityModeCommand &msg); From 8755c10cada0e17007cb8e1727b1e499a5f11204 Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 19:36:00 +0300 Subject: [PATCH 53/56] Authentication abnormal case handling --- src/ue/nas/mm/auth.cpp | 26 +++++++++++++++++++------- src/ue/nas/mm/mm.hpp | 4 +++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index bb08ce3fd..c565cc5df 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -216,6 +216,8 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms sendNasMessage(response); } + + // TODO (dont forget: m_nwConsecutiveAuthFailure = 0;) } void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &msg) @@ -279,8 +281,10 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & if ((m_usim->m_currentNsCtx && m_usim->m_currentNsCtx->ngKsi == msg.ngKSI.ksi) || (m_usim->m_nonCurrentNsCtx && m_usim->m_nonCurrentNsCtx->ngKsi == msg.ngKSI.ksi)) { - m_timers->t3520.start(); + if (networkFailingTheAuthCheck()) + return; + m_timers->t3520.start(); sendFailure(nas::EMmCause::NGKSI_ALREADY_IN_USE); return; } @@ -323,6 +327,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & keys::DeriveKeysSeafAmf(*m_base->config, *m_usim->m_currentPlmn, *m_usim->m_nonCurrentNsCtx); // Send response + m_nwConsecutiveAuthFailure = 0; m_timers->t3520.stop(); nas::AuthenticationResponse resp; @@ -333,23 +338,27 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else if (autnCheck == EAutnValidationRes::MAC_FAILURE) { + if (networkFailingTheAuthCheck()) + return; m_timers->t3520.start(); - sendFailure(nas::EMmCause::MAC_FAILURE); } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) { + if (networkFailingTheAuthCheck()) + return; + m_timers->t3520.start(); auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, true); auto auts = keys::CalculateAuts(m_usim->m_sqnMng->getSqn(), milenage.ak_r, milenage.mac_s); sendFailure(nas::EMmCause::SYNCH_FAILURE, std::move(auts)); } - else + else // the other case, separation bit mismatched { + if (networkFailingTheAuthCheck()) + return; m_timers->t3520.start(); - - // the other case, separation bit mismatched sendFailure(nas::EMmCause::NON_5G_AUTHENTICATION_UNACCEPTABLE); } } @@ -484,12 +493,15 @@ crypto::milenage::Milenage NasMm::calculateMilenage(const OctetString &sqn, cons return crypto::milenage::Calculate(opc, m_base->config->key, rand, sqn, amf); } -void NasMm::networkFailingTheAuth() +bool NasMm::networkFailingTheAuthCheck() { + if (m_nwConsecutiveAuthFailure++ < 3) + return false; + m_logger->err("Network failing the authentication check"); localReleaseConnection(); - // TODO: treat the active cell as barred + return true; } } // namespace nr::ue \ No newline at end of file diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index 8a5c0bd40..fc42b44ae 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -60,6 +60,8 @@ class NasMm nas::IE5gsNetworkFeatureSupport m_nwFeatureSupport{}; // Last time Service Request needed indication for Data long m_lastTimeServiceReqNeededIndForData{}; + // Number of times the network failing the authentication check + int m_nwConsecutiveAuthFailure{}; friend class UeCmdHandler; @@ -116,7 +118,7 @@ class NasMm void receiveEapResponseMessage(const eap::Eap &eap); EAutnValidationRes validateAutn(const OctetString &rand, const OctetString &autn); crypto::milenage::Milenage calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf); - void networkFailingTheAuth(); + bool networkFailingTheAuthCheck(); private: /* Security */ void receiveSecurityModeCommand(const nas::SecurityModeCommand &msg); From 91c7fec81d6dc3549442427fe4558f8cbbf3448b Mon Sep 17 00:00:00 2001 From: aligungr Date: Mon, 26 Apr 2021 19:45:41 +0300 Subject: [PATCH 54/56] Authentication abnormal case handling --- src/ue/nas/mm/auth.cpp | 19 +++++++++++++------ src/ue/nas/mm/mm.hpp | 2 +- src/ue/nas/mm/timer.cpp | 5 +++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/ue/nas/mm/auth.cpp b/src/ue/nas/mm/auth.cpp index c565cc5df..038efa639 100644 --- a/src/ue/nas/mm/auth.cpp +++ b/src/ue/nas/mm/auth.cpp @@ -281,7 +281,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & if ((m_usim->m_currentNsCtx && m_usim->m_currentNsCtx->ngKsi == msg.ngKSI.ksi) || (m_usim->m_nonCurrentNsCtx && m_usim->m_nonCurrentNsCtx->ngKsi == msg.ngKSI.ksi)) { - if (networkFailingTheAuthCheck()) + if (networkFailingTheAuthCheck(true)) return; m_timers->t3520.start(); @@ -338,14 +338,14 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else if (autnCheck == EAutnValidationRes::MAC_FAILURE) { - if (networkFailingTheAuthCheck()) + if (networkFailingTheAuthCheck(true)) return; m_timers->t3520.start(); sendFailure(nas::EMmCause::MAC_FAILURE); } else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) { - if (networkFailingTheAuthCheck()) + if (networkFailingTheAuthCheck(true)) return; m_timers->t3520.start(); @@ -356,7 +356,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & } else // the other case, separation bit mismatched { - if (networkFailingTheAuthCheck()) + if (networkFailingTheAuthCheck(true)) return; m_timers->t3520.start(); sendFailure(nas::EMmCause::NON_5G_AUTHENTICATION_UNACCEPTABLE); @@ -493,11 +493,18 @@ crypto::milenage::Milenage NasMm::calculateMilenage(const OctetString &sqn, cons return crypto::milenage::Calculate(opc, m_base->config->key, rand, sqn, amf); } -bool NasMm::networkFailingTheAuthCheck() +bool NasMm::networkFailingTheAuthCheck(bool hasChance) { - if (m_nwConsecutiveAuthFailure++ < 3) + if (hasChance && m_nwConsecutiveAuthFailure++ < 3) return false; + // NOTE: Normally if we should check if the UE has an emergency. If it has, it should consider as network passed the + // auth check, instead of performing the actions in the following lines. But it's difficult to maintain and + // implement this behaviour. Therefore we would expect other solutions for an emergency case. Such as + // - Network initiates a Security Mode Command with IA0 and EA0 + // - UE performs emergency registration after releasing the connection + // END + m_logger->err("Network failing the authentication check"); localReleaseConnection(); // TODO: treat the active cell as barred diff --git a/src/ue/nas/mm/mm.hpp b/src/ue/nas/mm/mm.hpp index fc42b44ae..8f72b49e5 100644 --- a/src/ue/nas/mm/mm.hpp +++ b/src/ue/nas/mm/mm.hpp @@ -118,7 +118,7 @@ class NasMm void receiveEapResponseMessage(const eap::Eap &eap); EAutnValidationRes validateAutn(const OctetString &rand, const OctetString &autn); crypto::milenage::Milenage calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf); - bool networkFailingTheAuthCheck(); + bool networkFailingTheAuthCheck(bool hasChance); private: /* Security */ void receiveSecurityModeCommand(const nas::SecurityModeCommand &msg); diff --git a/src/ue/nas/mm/timer.cpp b/src/ue/nas/mm/timer.cpp index 2c63227d9..9b94cbda9 100644 --- a/src/ue/nas/mm/timer.cpp +++ b/src/ue/nas/mm/timer.cpp @@ -114,6 +114,11 @@ void NasMm::onTimerExpire(nas::NasTimer &timer) m_usim->m_storedSuci = {}; break; } + case 3520: { + logExpired(); + networkFailingTheAuthCheck(false); + break; + } case 3521: { if (timer.getExpiryCount() == 5) { From 242e49486f8a3f460f685bdb4d9ad881969ac712 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sat, 1 May 2021 17:14:56 +0300 Subject: [PATCH 55/56] RLS dissector refactored --- tools/rls-wireshark-dissector.lua | 33 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/tools/rls-wireshark-dissector.lua b/tools/rls-wireshark-dissector.lua index eaca68854..9b1109db1 100644 --- a/tools/rls-wireshark-dissector.lua +++ b/tools/rls-wireshark-dissector.lua @@ -1,7 +1,6 @@ --[[ -- Dissector for Radio Link Simulation Protocol -- (used by UERANSIM ). --- When this dissector was written, UERANSIM was in version 3.1.7. -- -- CC0-1.0 2021 - Louis Royer () --]] @@ -30,14 +29,14 @@ local sim_pos_y = ProtoField.uint32("rls.sim_pos_y", "RLS Position Y", base.DEC) local sim_pos_z = ProtoField.uint32("rls.sim_pos_z", "RLS Position Z", base.DEC) -- For cell Info Response -local mcc = ProtoField.uint16("rls.mmc", "RLS MMC", base.DEC) -local mnc = ProtoField.uint16("rls.mnc", "RLS MNC", base.DEC) -local long_mnc = ProtoField.bool("rls.long_mnc", "RLS MNC is long", base.BOOL) -local nci = ProtoField.uint64("rls.nci", "RLS New Radio Cell Identity", base.HEX) -local tac = ProtoField.uint32("rls.tac", "RLS Tracking Area Code", base.DEC) +local mcc = ProtoField.uint16("rls.mcc", "MCC", base.DEC) +local mnc = ProtoField.uint16("rls.mnc", "MNC", base.DEC) +local long_mnc = ProtoField.bool("rls.long_mnc", "MNC is 3-digit", base.BOOL) +local nci = ProtoField.uint64("rls.nci", "NR Cell Identity", base.HEX) +local tac = ProtoField.uint32("rls.tac", "Tracking Area Code", base.DEC) local dbm = ProtoField.int32("rls.dbm", "RLS Signal Strength (dBm)", base.DEC) -local gnb_name = ProtoField.string("rls.gnb_name", "RLS gNb name") -local link_ip = ProtoField.string("rls.link_ip", "RLS gNb Link IP") +local gnb_name = ProtoField.string("rls.gnb_name", "gNB Name") +local link_ip = ProtoField.string("rls.link_ip", "gNB Link IP") -- For PDU Delivery local pdu_type_name = { @@ -49,14 +48,14 @@ local pdu_type_name = { local pdu_type = ProtoField.uint8("rls.pdu_type", "RLS PDU Type", base.DEC, pdu_type_name) local rrc_channel_name = { - [0] = "BCCH_BCH", - [1] = "BCCH_DL_SCH", - [2] = "DL_CCCH", - [3] = "DL_DCCH", + [0] = "BCCH-BCH", + [1] = "BCCH-DL-SCH", + [2] = "DL-CCCH", + [3] = "DL-DCCH", [4] = "PCCH", - [5] = "UL_CCCH", - [6] = "UL_CCCH1", - [7] = "UL_DCCH", + [5] = "UL-CCCH", + [6] = "UL-CCCH1", + [7] = "UL-DCCH", } local rrc_channel_dissector = { @@ -71,7 +70,7 @@ local rrc_channel_dissector = { } local rrc_channel = ProtoField.uint32("rls.rrc_channel", "RRC Channel", base.DEC, rrc_channel_name) -local session_id = ProtoField.uint32("rls.session_id", "RLS Session ID", base.DEC) +local session_id = ProtoField.uint32("rls.session_id", "PDU Session ID", base.DEC) --[[ -- Dissector definition @@ -109,7 +108,7 @@ function rls_protocol.dissector(buffer, pinfo, tree) subtree:add(sim_pos_z, buffer(21,4)) elseif msg_type == 2 then -- Cell Info Response subtree:add(mcc, buffer(13,2)) - local mnc_tree = subtree:add(rls_protocol, buffer(15,3), "RLS MNC: "..tostring(buffer(15,2):uint())) + local mnc_tree = subtree:add(rls_protocol, buffer(15,3), "MNC: "..tostring(buffer(15,2):uint())) mnc_tree:add(mnc, buffer(15,2)) mnc_tree:add(long_mnc, buffer(17,1)) subtree:add(nci, buffer(18,8)) From 1d85281c83d7a0e14ae38a263b9696035659d4e3 Mon Sep 17 00:00:00 2001 From: aligungr Date: Sat, 1 May 2021 17:16:59 +0300 Subject: [PATCH 56/56] Release of v3.1.8 --- README.md | 2 +- src/utils/constants.hpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 29e44673c..db550d239 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

- +

diff --git a/src/utils/constants.hpp b/src/utils/constants.hpp index 25d8e80ab..38e2351ce 100644 --- a/src/utils/constants.hpp +++ b/src/utils/constants.hpp @@ -15,10 +15,10 @@ struct cons // Version information static constexpr const uint8_t Major = 3; static constexpr const uint8_t Minor = 1; - static constexpr const uint8_t Patch = 7; + static constexpr const uint8_t Patch = 8; static constexpr const char *Project = "UERANSIM"; - static constexpr const char *Tag = "v3.1.7"; - static constexpr const char *Name = "UERANSIM v3.1.7"; + static constexpr const char *Tag = "v3.1.8"; + static constexpr const char *Name = "UERANSIM v3.1.8"; static constexpr const char *Owner = "ALİ GÜNGÖR"; // Some port values