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