Commit 611a2ea4 authored by aligungr's avatar aligungr

UE authentication procedure improvements

parent 9a36d694
...@@ -74,7 +74,6 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms ...@@ -74,7 +74,6 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms
auto &ck = milenage.ck; auto &ck = milenage.ck;
auto &ik = milenage.ik; auto &ik = milenage.ik;
auto &milenageAk = milenage.ak; auto &milenageAk = milenage.ak;
auto &milenageMac = milenage.mac_a;
auto sqnXorAk = OctetString::Xor(m_usim->m_sqnMng->getSqn(), milenageAk); auto sqnXorAk = OctetString::Xor(m_usim->m_sqnMng->getSqn(), milenageAk);
auto ckPrimeIkPrime = auto ckPrimeIkPrime =
...@@ -123,7 +122,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms ...@@ -123,7 +122,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms
} }
// Control received AUTN // Control received AUTN
auto autnCheck = validateAutn(milenageAk, milenageMac, receivedAutn); auto autnCheck = validateAutn(receivedRand, receivedAutn);
if (autnCheck != EAutnValidationRes::OK) if (autnCheck != EAutnValidationRes::OK)
{ {
eap::EapAkaPrime *eapResponse = nullptr; eap::EapAkaPrime *eapResponse = nullptr;
...@@ -289,30 +288,26 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & ...@@ -289,30 +288,26 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &
auto &rand = msg.authParamRAND->value; auto &rand = msg.authParamRAND->value;
auto &autn = msg.authParamAUTN->value; auto &autn = msg.authParamAUTN->value;
auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, false); auto autnCheck = validateAutn(rand, autn);
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);
if (autnCheck == EAutnValidationRes::OK) 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 // Store the relevant parameters
m_usim->m_rand = rand.copy(); m_usim->m_rand = rand.copy();
m_usim->m_resStar = keys::CalculateResStar(ckIk, snn, rand, res); m_usim->m_resStar = keys::CalculateResStar(ckIk, snn, rand, milenage.res);
m_usim->m_res = std::move(res); m_usim->m_res = milenage.res.copy();
// Create new partial native NAS security context and continue with key derivation // Create new partial native NAS security context and continue with key derivation
m_usim->m_nonCurrentNsCtx = std::make_unique<NasSecurityContext>(); m_usim->m_nonCurrentNsCtx = std::make_unique<NasSecurityContext>();
m_usim->m_nonCurrentNsCtx->tsc = msg.ngKSI.tsc; m_usim->m_nonCurrentNsCtx->tsc = msg.ngKSI.tsc;
m_usim->m_nonCurrentNsCtx->ngKsi = msg.ngKSI.ksi; 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(); m_usim->m_nonCurrentNsCtx->keys.abba = msg.abba.rawData.copy();
keys::DeriveKeysSeafAmf(*m_base->config, *m_usim->m_currentPlmn, *m_usim->m_nonCurrentNsCtx); keys::DeriveKeysSeafAmf(*m_base->config, *m_usim->m_currentPlmn, *m_usim->m_nonCurrentNsCtx);
...@@ -329,8 +324,8 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest & ...@@ -329,8 +324,8 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &
} }
else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE) else if (autnCheck == EAutnValidationRes::SYNCHRONISATION_FAILURE)
{ {
auto milenageForSync = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, true); auto milenage = calculateMilenage(m_usim->m_sqnMng->getSqn(), rand, true);
auto auts = keys::CalculateAuts(m_usim->m_sqnMng->getSqn(), milenageForSync.ak_r, milenageForSync.mac_s); auto auts = keys::CalculateAuts(m_usim->m_sqnMng->getSqn(), milenage.ak_r, milenage.mac_s);
sendFailure(nas::EMmCause::SYNCH_FAILURE, std::move(auts)); sendFailure(nas::EMmCause::SYNCH_FAILURE, std::move(auts));
} }
else else
...@@ -418,30 +413,35 @@ void NasMm::receiveEapResponseMessage(const eap::Eap &eap) ...@@ -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 // Decode AUTN
OctetString receivedSQNxorAK = autn.subCopy(0, 6); OctetString receivedSQNxorAK = autn.subCopy(0, 6);
OctetString receivedSQN = OctetString::Xor(receivedSQNxorAK, ak);
OctetString receivedAMF = autn.subCopy(6, 2); OctetString receivedAMF = autn.subCopy(6, 2);
OctetString receivedMAC = autn.subCopy(8, 8); 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 // Check the separation bit
// 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) if (receivedAMF.get(0).bit(7) != 1)
{ {
m_logger->err("AUTN validation SEP-BIT failure. expected: 1, received: 0"); m_logger->err("AUTN validation SEP-BIT failure. expected: 1, received: 0");
return EAutnValidationRes::AMF_SEPARATION_BIT_FAILURE; 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 // Verify that the received sequence number SQN is in the correct range
if (!m_usim->m_sqnMng->checkSqn(receivedSQN)) if (!m_usim->m_sqnMng->checkSqn(receivedSQN))
return EAutnValidationRes::SYNCHRONISATION_FAILURE; 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 // 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()); receivedMAC.toHexString().c_str());
return EAutnValidationRes::MAC_FAILURE; return EAutnValidationRes::MAC_FAILURE;
} }
......
...@@ -114,7 +114,7 @@ class NasMm ...@@ -114,7 +114,7 @@ class NasMm
void receiveEapSuccessMessage(const eap::Eap &eap); void receiveEapSuccessMessage(const eap::Eap &eap);
void receiveEapFailureMessage(const eap::Eap &eap); void receiveEapFailureMessage(const eap::Eap &eap);
void receiveEapResponseMessage(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); crypto::milenage::Milenage calculateMilenage(const OctetString &sqn, const OctetString &rand, bool dummyAmf);
private: /* Security */ private: /* Security */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment