Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
U
UERANSIM
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
UERANSIM
Commits
31196a88
Commit
31196a88
authored
Feb 23, 2021
by
aligungr
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Mobile storage refactor
parent
4097d4e6
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
211 additions
and
142 deletions
+211
-142
src/ue/app/cmd_handler.cpp
src/ue/app/cmd_handler.cpp
+5
-5
src/ue/mm/auth.cpp
src/ue/mm/auth.cpp
+41
-40
src/ue/mm/base.cpp
src/ue/mm/base.cpp
+10
-26
src/ue/mm/config.cpp
src/ue/mm/config.cpp
+3
-3
src/ue/mm/dereg.cpp
src/ue/mm/dereg.cpp
+8
-8
src/ue/mm/identity.cpp
src/ue/mm/identity.cpp
+6
-6
src/ue/mm/mm.hpp
src/ue/mm/mm.hpp
+7
-17
src/ue/mm/register.cpp
src/ue/mm/register.cpp
+12
-21
src/ue/mm/security.cpp
src/ue/mm/security.cpp
+10
-10
src/ue/mm/transport.cpp
src/ue/mm/transport.cpp
+7
-6
src/ue/nas/storage.cpp
src/ue/nas/storage.cpp
+14
-0
src/ue/nas/storage.hpp
src/ue/nas/storage.hpp
+88
-0
No files found.
src/ue/app/cmd_handler.cpp
View file @
31196a88
...
...
@@ -109,9 +109,9 @@ void UeCmdHandler::handleCmdImpl(NwUeCliCommand &msg)
{
"cm-state"
,
ToJson
(
m_base
->
nasTask
->
mm
->
m_cmState
)},
{
"rm-state"
,
ToJson
(
m_base
->
nasTask
->
mm
->
m_rmState
)},
{
"mm-state"
,
ToJson
(
m_base
->
nasTask
->
mm
->
m_mmSubState
)},
{
"sim-inserted"
,
m_base
->
nasTask
->
mm
->
m_
validSim
},
{
"stored-suci"
,
ToJson
(
m_base
->
nasTask
->
mm
->
m_storedSuci
)},
{
"stored-guti"
,
ToJson
(
m_base
->
nasTask
->
mm
->
m_storedGuti
)},
{
"sim-inserted"
,
m_base
->
nasTask
->
mm
->
m_
storage
.
isSimValid
()
},
{
"stored-suci"
,
ToJson
(
m_base
->
nasTask
->
mm
->
m_stor
age
.
m_stor
edSuci
)},
{
"stored-guti"
,
ToJson
(
m_base
->
nasTask
->
mm
->
m_stor
age
.
m_stor
edGuti
)},
{
"pdu-sessions"
,
Json
::
Arr
(
std
::
move
(
pduSessions
))},
});
sendResult
(
msg
.
address
,
json
.
dumpYaml
());
...
...
src/ue/mm/auth.cpp
View file @
31196a88
...
...
@@ -17,7 +17,7 @@ namespace nr::ue
void
NasMm
::
receiveAuthenticationRequest
(
const
nas
::
AuthenticationRequest
&
msg
)
{
if
(
!
m_
validSim
)
if
(
!
m_
storage
.
isSimValid
()
)
{
m_logger
->
warn
(
"Authentication request is ignored. USIM is invalid"
);
return
;
...
...
@@ -67,17 +67,17 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms
if
(
USE_SQN_HACK
)
{
auto
ak
=
calculateMilenage
(
OctetString
::
FromSpare
(
6
),
receivedRand
).
ak
;
m_sqn
=
OctetString
::
Xor
(
receivedAutn
.
subCopy
(
0
,
6
),
ak
);
m_s
torage
.
m_s
qn
=
OctetString
::
Xor
(
receivedAutn
.
subCopy
(
0
,
6
),
ak
);
}
auto
milenage
=
calculateMilenage
(
m_sqn
,
receivedRand
);
auto
milenage
=
calculateMilenage
(
m_s
torage
.
m_s
qn
,
receivedRand
);
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_sqn
,
milenageAk
);
auto
sqnXorAk
=
OctetString
::
Xor
(
m_s
torage
.
m_s
qn
,
milenageAk
);
auto
ckPrimeIkPrime
=
keys
::
CalculateCkPrimeIkPrime
(
ck
,
ik
,
keys
::
ConstructServingNetworkName
(
m_base
->
config
->
plmn
),
sqnXorAk
);
auto
&
ckPrime
=
ckPrimeIkPrime
.
first
;
...
...
@@ -92,7 +92,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms
auto
mk
=
keys
::
CalculateMk
(
ckPrime
,
ikPrime
,
m_base
->
config
->
supi
.
value
());
auto
kaut
=
mk
.
subCopy
(
16
,
32
);
m_logger
->
debug
(
"ueData.sqn: %s"
,
m_sqn
.
toHexString
().
c_str
());
m_logger
->
debug
(
"ueData.sqn: %s"
,
m_s
torage
.
m_s
qn
.
toHexString
().
c_str
());
m_logger
->
debug
(
"ueData.op(C): %s"
,
m_base
->
config
->
opC
.
toHexString
().
c_str
());
m_logger
->
debug
(
"ueData.K: %s"
,
m_base
->
config
->
key
.
toHexString
().
c_str
());
m_logger
->
debug
(
"calculated res: %s"
,
res
.
toHexString
().
c_str
());
...
...
@@ -188,25 +188,25 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms
auto
kAusf
=
keys
::
CalculateKAusfForEapAkaPrime
(
mk
);
m_logger
->
debug
(
"kAusf: %s"
,
kAusf
.
toHexString
().
c_str
());
m_nonCurrentNsCtx
=
NasSecurityContext
{};
m_nonCurrentNsCtx
->
tsc
=
msg
.
ngKSI
.
tsc
;
m_nonCurrentNsCtx
->
ngKsi
=
msg
.
ngKSI
.
ksi
;
m_nonCurrentNsCtx
->
keys
.
rand
=
std
::
move
(
receivedRand
);
m_nonCurrentNsCtx
->
keys
.
res
=
std
::
move
(
res
);
m_nonCurrentNsCtx
->
keys
.
resStar
=
{};
m_nonCurrentNsCtx
->
keys
.
kAusf
=
std
::
move
(
kAusf
);
m_nonCurrentNsCtx
->
keys
.
abba
=
msg
.
abba
.
rawData
.
copy
();
m_
storage
.
m_
nonCurrentNsCtx
=
NasSecurityContext
{};
m_
storage
.
m_
nonCurrentNsCtx
->
tsc
=
msg
.
ngKSI
.
tsc
;
m_
storage
.
m_
nonCurrentNsCtx
->
ngKsi
=
msg
.
ngKSI
.
ksi
;
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
rand
=
std
::
move
(
receivedRand
);
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
res
=
std
::
move
(
res
);
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
resStar
=
{};
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
kAusf
=
std
::
move
(
kAusf
);
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
abba
=
msg
.
abba
.
rawData
.
copy
();
keys
::
DeriveKeysSeafAmf
(
*
m_base
->
config
,
*
m_nonCurrentNsCtx
);
keys
::
DeriveKeysSeafAmf
(
*
m_base
->
config
,
*
m_
storage
.
m_
nonCurrentNsCtx
);
m_logger
->
debug
(
"kSeaf: %s"
,
m_nonCurrentNsCtx
->
keys
.
kSeaf
.
toHexString
().
c_str
());
m_logger
->
debug
(
"kAmf: %s"
,
m_nonCurrentNsCtx
->
keys
.
kAmf
.
toHexString
().
c_str
());
m_logger
->
debug
(
"kSeaf: %s"
,
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
kSeaf
.
toHexString
().
c_str
());
m_logger
->
debug
(
"kAmf: %s"
,
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
kAmf
.
toHexString
().
c_str
());
// Send Response
{
auto
*
akaPrimeResponse
=
new
eap
::
EapAkaPrime
(
eap
::
ECode
::
RESPONSE
,
receivedEap
.
id
,
eap
::
ESubType
::
AKA_CHALLENGE
);
akaPrimeResponse
->
attributes
.
putRes
(
m_nonCurrentNsCtx
->
keys
.
res
);
akaPrimeResponse
->
attributes
.
putRes
(
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
res
);
akaPrimeResponse
->
attributes
.
putMac
(
OctetString
::
FromSpare
(
16
));
// Dummy mac for now
akaPrimeResponse
->
attributes
.
putKdf
(
1
);
...
...
@@ -254,48 +254,49 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &
if
(
USE_SQN_HACK
)
{
auto
ak
=
calculateMilenage
(
OctetString
::
FromSpare
(
6
),
rand
).
ak
;
m_sqn
=
OctetString
::
Xor
(
autn
.
subCopy
(
0
,
6
),
ak
);
m_s
torage
.
m_s
qn
=
OctetString
::
Xor
(
autn
.
subCopy
(
0
,
6
),
ak
);
}
auto
milenage
=
calculateMilenage
(
m_sqn
,
rand
);
auto
milenage
=
calculateMilenage
(
m_s
torage
.
m_s
qn
,
rand
);
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_sqn
,
milenageAk
);
auto
sqnXorAk
=
OctetString
::
Xor
(
m_s
torage
.
m_s
qn
,
milenageAk
);
auto
snn
=
keys
::
ConstructServingNetworkName
(
m_base
->
config
->
plmn
);
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_sqn
.
toHexString
().
c_str
());
m_logger
->
debug
(
"Used snn[%s] sqn[%s]"
,
snn
.
c_str
(),
m_s
torage
.
m_s
qn
.
toHexString
().
c_str
());
auto
autnCheck
=
validateAutn
(
milenageAk
,
milenageMac
,
autn
);
if
(
IGNORE_CONTROLS_FAILURES
||
autnCheck
==
EAutnValidationRes
::
OK
)
{
// Create new partial native NAS security context and continue with key derivation
m_nonCurrentNsCtx
=
NasSecurityContext
{};
m_nonCurrentNsCtx
->
tsc
=
msg
.
ngKSI
.
tsc
;
m_nonCurrentNsCtx
->
ngKsi
=
msg
.
ngKSI
.
ksi
;
m_nonCurrentNsCtx
->
keys
.
rand
=
rand
.
copy
();
m_nonCurrentNsCtx
->
keys
.
resStar
=
keys
::
CalculateResStar
(
ckIk
,
snn
,
rand
,
res
);
m_nonCurrentNsCtx
->
keys
.
res
=
std
::
move
(
res
);
m_nonCurrentNsCtx
->
keys
.
kAusf
=
keys
::
CalculateKAusfFor5gAka
(
ck
,
ik
,
snn
,
sqnXorAk
);
m_nonCurrentNsCtx
->
keys
.
abba
=
msg
.
abba
.
rawData
.
copy
();
keys
::
DeriveKeysSeafAmf
(
*
m_base
->
config
,
*
m_nonCurrentNsCtx
);
m_logger
->
debug
(
"Derived kSeaf[%s] kAusf[%s] kAmf[%s]"
,
m_nonCurrentNsCtx
->
keys
.
kSeaf
.
toHexString
().
c_str
(),
m_nonCurrentNsCtx
->
keys
.
kAusf
.
toHexString
().
c_str
(),
m_nonCurrentNsCtx
->
keys
.
kAmf
.
toHexString
().
c_str
());
m_storage
.
m_nonCurrentNsCtx
=
NasSecurityContext
{};
m_storage
.
m_nonCurrentNsCtx
->
tsc
=
msg
.
ngKSI
.
tsc
;
m_storage
.
m_nonCurrentNsCtx
->
ngKsi
=
msg
.
ngKSI
.
ksi
;
m_storage
.
m_nonCurrentNsCtx
->
keys
.
rand
=
rand
.
copy
();
m_storage
.
m_nonCurrentNsCtx
->
keys
.
resStar
=
keys
::
CalculateResStar
(
ckIk
,
snn
,
rand
,
res
);
m_storage
.
m_nonCurrentNsCtx
->
keys
.
res
=
std
::
move
(
res
);
m_storage
.
m_nonCurrentNsCtx
->
keys
.
kAusf
=
keys
::
CalculateKAusfFor5gAka
(
ck
,
ik
,
snn
,
sqnXorAk
);
m_storage
.
m_nonCurrentNsCtx
->
keys
.
abba
=
msg
.
abba
.
rawData
.
copy
();
keys
::
DeriveKeysSeafAmf
(
*
m_base
->
config
,
*
m_storage
.
m_nonCurrentNsCtx
);
m_logger
->
debug
(
"Derived kSeaf[%s] kAusf[%s] kAmf[%s]"
,
m_storage
.
m_nonCurrentNsCtx
->
keys
.
kSeaf
.
toHexString
().
c_str
(),
m_storage
.
m_nonCurrentNsCtx
->
keys
.
kAusf
.
toHexString
().
c_str
(),
m_storage
.
m_nonCurrentNsCtx
->
keys
.
kAmf
.
toHexString
().
c_str
());
// Send response
nas
::
AuthenticationResponse
resp
;
resp
.
authenticationResponseParameter
=
nas
::
IEAuthenticationResponseParameter
{};
resp
.
authenticationResponseParameter
->
rawData
=
m_nonCurrentNsCtx
->
keys
.
resStar
.
copy
();
resp
.
authenticationResponseParameter
->
rawData
=
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
resStar
.
copy
();
sendNasMessage
(
resp
);
}
else
if
(
autnCheck
==
EAutnValidationRes
::
MAC_FAILURE
)
...
...
@@ -317,7 +318,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &
void
NasMm
::
receiveAuthenticationResult
(
const
nas
::
AuthenticationResult
&
msg
)
{
if
(
msg
.
abba
.
has_value
())
m_nonCurrentNsCtx
->
keys
.
abba
=
msg
.
abba
->
rawData
.
copy
();
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
abba
=
msg
.
abba
->
rawData
.
copy
();
if
(
msg
.
eapMessage
.
eap
->
code
==
eap
::
ECode
::
SUCCESS
)
receiveEapSuccessMessage
(
*
msg
.
eapMessage
.
eap
);
...
...
@@ -350,9 +351,9 @@ void NasMm::receiveAuthenticationReject(const nas::AuthenticationReject &msg)
// The UE shall set the update status to 5U3 ROAMING NOT ALLOWED,
switchUState
(
E5UState
::
U3_ROAMING_NOT_ALLOWED
);
// Delete the stored 5G-GUTI, TAI list, last visited registered TAI and ngKSI The USIM shall be considered invalid
// Delete the stored 5G-GUTI, TAI list, last visited registered TAI and ngKSI
.
The USIM shall be considered invalid
// until switching off the UE or the UICC containing the USIM is removed
invalidateSim
();
m_storage
.
invalidateSim
();
// The UE shall abort any 5GMM signalling procedure, stop any of the timers T3510, T3516, T3517, T3519 or T3521 (if
// they were running) ..
m_timers
->
t3510
.
stop
();
...
...
@@ -372,7 +373,7 @@ void NasMm::receiveEapSuccessMessage(const eap::Eap &eap)
void
NasMm
::
receiveEapFailureMessage
(
const
eap
::
Eap
&
eap
)
{
m_logger
->
err
(
"EAP failure received. Deleting non-current NAS security context"
);
m_nonCurrentNsCtx
=
{};
m_
storage
.
m_
nonCurrentNsCtx
=
{};
}
void
NasMm
::
receiveEapResponseMessage
(
const
eap
::
Eap
&
eap
)
...
...
src/ue/mm/base.cpp
View file @
31196a88
...
...
@@ -25,9 +25,9 @@ NasMm::NasMm(TaskBase *base, UeTimers *timers) : m_base{base}, m_timers{timers},
m_cmState
=
ECmState
::
CM_IDLE
;
m_mmState
=
EMmState
::
MM_DEREGISTERED
;
m_mmSubState
=
EMmSubState
::
MM_DEREGISTERED_NA
;
m_uState
=
E5UState
::
U1_UPDATED
;
m_
storage
.
m_
uState
=
E5UState
::
U1_UPDATED
;
m_autoBehaviour
=
base
->
config
->
autoBehaviour
;
m_
validSim
=
base
->
config
->
supi
.
has_value
(
);
m_
storage
.
initialize
(
base
->
config
->
supi
.
has_value
()
);
}
void
NasMm
::
onStart
(
NasSm
*
sm
)
...
...
@@ -52,7 +52,7 @@ void NasMm::performMmCycle()
if
(
m_mmSubState
==
EMmSubState
::
MM_DEREGISTERED_NA
)
{
if
(
m_
validSim
)
if
(
m_
storage
.
isSimValid
()
)
{
if
(
m_cmState
==
ECmState
::
CM_IDLE
)
switchMmState
(
EMmState
::
MM_DEREGISTERED
,
EMmSubState
::
MM_DEREGISTERED_PLMN_SEARCH
);
...
...
@@ -168,15 +168,15 @@ void NasMm::switchCmState(ECmState state)
void
NasMm
::
switchUState
(
E5UState
state
)
{
E5UState
oldState
=
m_uState
;
m_uState
=
state
;
E5UState
oldState
=
m_
storage
.
m_
uState
;
m_
storage
.
m_
uState
=
state
;
onSwitchUState
(
oldState
,
m_uState
);
onSwitchUState
(
oldState
,
m_
storage
.
m_
uState
);
if
(
m_base
->
nodeListener
)
{
m_base
->
nodeListener
->
onSwitch
(
app
::
NodeType
::
UE
,
m_base
->
config
->
getNodeName
(),
app
::
StateType
::
U5
,
ToJson
(
oldState
).
str
(),
ToJson
(
m_uState
).
str
());
ToJson
(
oldState
).
str
(),
ToJson
(
m_
storage
.
m_
uState
).
str
());
}
if
(
state
!=
oldState
)
...
...
@@ -192,12 +192,12 @@ void NasMm::onSwitchMmState(EMmState oldState, EMmState newState, EMmSubState ol
// 5GMM-DEREGISTERED for any other state except 5GMM-NULL.
if
(
oldState
==
EMmState
::
MM_DEREGISTERED
&&
newState
!=
EMmState
::
MM_DEREGISTERED
&&
newState
!=
EMmState
::
MM_NULL
)
{
if
(
m_
currentNsCtx
.
has_value
()
||
m_nonCurrentNsCtx
.
has_value
())
if
(
m_
storage
.
m_currentNsCtx
.
has_value
()
||
m_storage
.
m_nonCurrentNsCtx
.
has_value
())
{
m_logger
->
debug
(
"Deleting NAS security context"
);
m_currentNsCtx
=
{};
m_nonCurrentNsCtx
=
{};
m_
storage
.
m_
currentNsCtx
=
{};
m_
storage
.
m_
nonCurrentNsCtx
=
{};
}
}
}
...
...
@@ -283,20 +283,4 @@ void NasMm::onTimerExpire(nas::NasTimer &timer)
}
}
void
NasMm
::
invalidateAcquiredParams
()
{
m_storedGuti
=
{};
m_lastVisitedRegisteredTai
=
{};
m_taiList
=
{};
m_currentNsCtx
=
{};
m_nonCurrentNsCtx
=
{};
}
void
NasMm
::
invalidateSim
()
{
m_logger
->
warn
(
"USIM is removed or invalidated"
);
m_validSim
=
false
;
invalidateAcquiredParams
();
}
}
// namespace nr::ue
src/ue/mm/config.cpp
View file @
31196a88
...
...
@@ -17,13 +17,13 @@ void NasMm::receiveConfigurationUpdate(const nas::ConfigurationUpdateCommand &ms
if
(
msg
.
guti
.
has_value
()
&&
msg
.
guti
->
type
==
nas
::
EIdentityType
::
GUTI
)
{
m_stor
edGuti
=
msg
.
guti
.
value
()
;
m_stor
edSuci
=
{}
;
m_stor
age
.
m_storedSuci
=
{}
;
m_stor
age
.
m_storedGuti
=
*
msg
.
guti
;
m_timers
->
t3519
.
stop
();
}
if
(
msg
.
taiList
.
has_value
())
m_taiList
=
msg
.
taiList
.
value
();
m_
storage
.
m_
taiList
=
msg
.
taiList
.
value
();
if
(
msg
.
configurationUpdateIndication
.
has_value
())
{
...
...
src/ue/mm/dereg.cpp
View file @
31196a88
...
...
@@ -30,10 +30,10 @@ void NasMm::sendDeregistration(nas::ESwitchOff switchOff, bool dueToDisable5g)
request
->
deRegistrationType
.
reRegistrationRequired
=
nas
::
EReRegistrationRequired
::
NOT_REQUIRED
;
request
->
deRegistrationType
.
switchOff
=
switchOff
;
if
(
m_currentNsCtx
.
has_value
())
if
(
m_
storage
.
m_
currentNsCtx
.
has_value
())
{
request
->
ngKSI
.
tsc
=
m_currentNsCtx
->
tsc
;
request
->
ngKSI
.
ksi
=
m_currentNsCtx
->
ngKsi
;
request
->
ngKSI
.
tsc
=
m_
storage
.
m_
currentNsCtx
->
tsc
;
request
->
ngKSI
.
ksi
=
m_
storage
.
m_
currentNsCtx
->
ngKsi
;
}
else
{
...
...
@@ -76,7 +76,7 @@ void NasMm::receiveDeregistrationAccept(const nas::DeRegistrationAcceptUeOrigina
m_timers
->
t3521
.
stop
();
m_timers
->
t3519
.
stop
();
m_storedSuci
=
{};
m_stor
age
.
m_stor
edSuci
=
{};
switchRmState
(
ERmState
::
RM_DEREGISTERED
);
...
...
@@ -162,7 +162,7 @@ void NasMm::receiveDeregistrationRequest(const nas::DeRegistrationRequestUeTermi
case
nas
:
:
EMmCause
::
ILLEGAL_ME
:
case
nas
:
:
EMmCause
::
FIVEG_SERVICES_NOT_ALLOWED
:
{
switchUState
(
E5UState
::
U3_ROAMING_NOT_ALLOWED
);
invalidateSim
();
m_storage
.
invalidateSim
();
switchMmState
(
EMmState
::
MM_DEREGISTERED
,
EMmSubState
::
MM_DEREGISTERED_NA
);
break
;
}
...
...
@@ -175,13 +175,13 @@ void NasMm::receiveDeregistrationRequest(const nas::DeRegistrationRequestUeTermi
//}
case
nas
:
:
EMmCause
::
TA_NOT_ALLOWED
:
{
switchUState
(
E5UState
::
U3_ROAMING_NOT_ALLOWED
);
invalidateAcquiredParams
();
m_storage
.
discardUsim
();
switchMmState
(
EMmState
::
MM_DEREGISTERED
,
EMmSubState
::
MM_DEREGISTERED_LIMITED_SERVICE
);
break
;
}
case
nas
:
:
EMmCause
::
N1_MODE_NOT_ALLOWED
:
{
switchUState
(
E5UState
::
U3_ROAMING_NOT_ALLOWED
);
invalidateAcquiredParams
();
m_storage
.
discardUsim
();
switchMmState
(
EMmState
::
MM_NULL
,
EMmSubState
::
MM_NULL_NA
);
break
;
}
...
...
@@ -198,7 +198,7 @@ void NasMm::receiveDeregistrationRequest(const nas::DeRegistrationRequestUeTermi
nas
::
utils
::
EnumToString
(
msg
.
mmCause
->
value
));
switchUState
(
E5UState
::
U3_ROAMING_NOT_ALLOWED
);
invalidateSim
();
m_storage
.
invalidateSim
();
switchMmState
(
EMmState
::
MM_DEREGISTERED
,
EMmSubState
::
MM_DEREGISTERED_NA
);
break
;
}
...
...
src/ue/mm/identity.cpp
View file @
31196a88
...
...
@@ -43,15 +43,15 @@ void NasMm::receiveIdentityRequest(const nas::IdentityRequest &msg)
nas
::
IE5gsMobileIdentity
NasMm
::
getOrGenerateSuci
()
{
if
(
m_timers
->
t3519
.
isRunning
())
return
m_storedSuci
;
return
m_stor
age
.
m_stor
edSuci
;
m_storedSuci
=
generateSuci
();
m_stor
age
.
m_stor
edSuci
=
generateSuci
();
m_timers
->
t3519
.
start
();
if
(
m_storedSuci
.
type
==
nas
::
EIdentityType
::
NO_IDENTITY
)
if
(
m_stor
age
.
m_stor
edSuci
.
type
==
nas
::
EIdentityType
::
NO_IDENTITY
)
return
{};
return
m_storedSuci
;
return
m_stor
age
.
m_stor
edSuci
;
}
nas
::
IE5gsMobileIdentity
NasMm
::
generateSuci
()
...
...
@@ -93,8 +93,8 @@ nas::IE5gsMobileIdentity NasMm::generateSuci()
nas
::
IE5gsMobileIdentity
NasMm
::
getOrGeneratePreferredId
()
{
if
(
m_storedGuti
.
type
!=
nas
::
EIdentityType
::
NO_IDENTITY
)
return
m_storedGuti
;
if
(
m_stor
age
.
m_stor
edGuti
.
type
!=
nas
::
EIdentityType
::
NO_IDENTITY
)
return
m_stor
age
.
m_stor
edGuti
;
else
{
auto
suci
=
getOrGenerateSuci
();
...
...
src/ue/mm/mm.hpp
View file @
31196a88
...
...
@@ -11,6 +11,7 @@
#include <crypt/milenage.hpp>
#include <nas/nas.hpp>
#include <nas/timer.hpp>
#include <ue/nas/storage.hpp>
#include <ue/nts.hpp>
#include <ue/types.hpp>
#include <utils/nts.hpp>
...
...
@@ -28,31 +29,22 @@ class NasMm
UeTimers
*
m_timers
;
std
::
unique_ptr
<
Logger
>
m_logger
;
NasSm
*
m_sm
;
MobileStorage
m_storage
{};
bool
m_autoBehaviour
;
ERmState
m_rmState
;
ECmState
m_cmState
;
EMmState
m_mmState
;
EMmSubState
m_mmSubState
;
E5UState
m_uState
;
nas
::
IE5gsMobileIdentity
m_storedSuci
{};
nas
::
IE5gsMobileIdentity
m_storedGuti
{};
// The very last registration request (or null)
std
::
unique_ptr
<
nas
::
RegistrationRequest
>
m_lastRegistrationRequest
{};
// The very last de-registration request (or null)
std
::
unique_ptr
<
nas
::
DeRegistrationRequestUeOriginating
>
m_lastDeregistrationRequest
{};
// Indicates that the last de-registration request is issued due to disable 5G services
bool
m_lastDeregDueToDisable5g
{};
std
::
optional
<
nas
::
IE5gsTrackingAreaIdentity
>
m_lastVisitedRegisteredTai
{};
std
::
optional
<
nas
::
IE5gsTrackingAreaIdentityList
>
m_taiList
{};
std
::
optional
<
NasSecurityContext
>
m_currentNsCtx
;
std
::
optional
<
NasSecurityContext
>
m_nonCurrentNsCtx
;
bool
m_autoBehaviour
;
bool
m_validSim
;
// Last time PLMN search is triggered
long
m_lastPlmnSearchTrigger
{};
OctetString
m_sqn
{};
friend
class
UeCmdHandler
;
...
...
@@ -91,8 +83,6 @@ class NasMm
void
onSwitchRmState
(
ERmState
oldState
,
ERmState
newState
);
void
onSwitchCmState
(
ECmState
oldState
,
ECmState
newState
);
void
onSwitchUState
(
E5UState
oldState
,
E5UState
newState
);
void
invalidateAcquiredParams
();
void
invalidateSim
();
/* Transport */
void
sendMmStatus
(
nas
::
EMmCause
cause
);
...
...
src/ue/mm/register.cpp
View file @
31196a88
...
...
@@ -19,19 +19,16 @@ void NasMm::sendRegistration(nas::ERegistrationType registrationType, nas::EFoll
// The UE shall mark the 5G NAS security context on the USIM or in the non-volatile memory as invalid when the UE
// initiates an initial registration procedure
if
(
registrationType
==
nas
::
ERegistrationType
::
INITIAL_REGISTRATION
)
{
m_currentNsCtx
=
{};
m_nonCurrentNsCtx
=
{};
}
m_storage
.
discardCurrentSecurity
();
switchMmState
(
EMmState
::
MM_REGISTERED_INITIATED
,
EMmSubState
::
MM_REGISTERED_INITIATED_NA
);
nas
::
IENasKeySetIdentifier
ngKsi
;
if
(
m_currentNsCtx
.
has_value
())
if
(
m_
storage
.
m_
currentNsCtx
.
has_value
())
{
ngKsi
.
tsc
=
m_currentNsCtx
->
tsc
;
ngKsi
.
ksi
=
m_currentNsCtx
->
ngKsi
;
ngKsi
.
tsc
=
m_
storage
.
m_
currentNsCtx
->
tsc
;
ngKsi
.
ksi
=
m_
storage
.
m_
currentNsCtx
->
ngKsi
;
}
auto
request
=
std
::
make_unique
<
nas
::
RegistrationRequest
>
();
...
...
@@ -52,8 +49,8 @@ void NasMm::sendRegistration(nas::ERegistrationType registrationType, nas::EFoll
request
->
mobileIdentity
=
getOrGeneratePreferredId
();
if
(
m_lastVisitedRegisteredTai
.
has_value
())
request
->
lastVisitedRegisteredTai
=
m_lastVisitedRegisteredTai
.
value
();
if
(
m_
storage
.
m_
lastVisitedRegisteredTai
.
has_value
())
request
->
lastVisitedRegisteredTai
=
m_
storage
.
m_
lastVisitedRegisteredTai
.
value
();
m_timers
->
t3510
.
start
();
m_timers
->
t3502
.
stop
();
...
...
@@ -73,7 +70,7 @@ void NasMm::receiveRegistrationAccept(const nas::RegistrationAccept &msg)
bool
sendCompleteMes
=
false
;
m_taiList
=
msg
.
taiList
;
m_
storage
.
m_
taiList
=
msg
.
taiList
;
if
(
msg
.
t3512Value
.
has_value
()
&&
nas
::
utils
::
HasValue
(
msg
.
t3512Value
.
value
()))
{
...
...
@@ -83,7 +80,7 @@ void NasMm::receiveRegistrationAccept(const nas::RegistrationAccept &msg)
if
(
msg
.
mobileIdentity
.
has_value
()
&&
msg
.
mobileIdentity
->
type
==
nas
::
EIdentityType
::
GUTI
)
{
m_storedGuti
=
msg
.
mobileIdentity
.
value
();
m_stor
age
.
m_stor
edGuti
=
msg
.
mobileIdentity
.
value
();
m_timers
->
t3519
.
stop
();
sendCompleteMes
=
true
;
...
...
@@ -122,6 +119,8 @@ void NasMm::receiveRegistrationReject(const nas::RegistrationReject &msg)
}
auto
unhandledRejectCase
=
[
cause
,
this
]()
{
m_storage
.
discardUsim
();
m_logger
->
err
(
"Registration rejected with unhandled MMCause: %s"
,
nas
::
utils
::
EnumToString
(
cause
));
switchMmState
(
EMmState
::
MM_DEREGISTERED
,
EMmSubState
::
MM_DEREGISTERED_NA
);
switchRmState
(
ERmState
::
RM_DEREGISTERED
);
...
...
@@ -134,11 +133,7 @@ void NasMm::receiveRegistrationReject(const nas::RegistrationReject &msg)
cause
==
nas
::
EMmCause
::
TA_NOT_ALLOWED
||
cause
==
nas
::
EMmCause
::
ROAMING_NOT_ALLOWED_IN_TA
||
cause
==
nas
::
EMmCause
::
NO_SUITIBLE_CELLS_IN_TA
)
{
m_storedGuti
=
{};
m_lastVisitedRegisteredTai
=
{};
m_taiList
=
{};
m_currentNsCtx
=
{};
m_nonCurrentNsCtx
=
{};
m_storage
.
discardUsim
();
// TODO Normally UE switches to PLMN SEARCH, but this leads to endless registration attempt again and again.
// due to RLS.
...
...
@@ -168,11 +163,7 @@ void NasMm::receiveRegistrationReject(const nas::RegistrationReject &msg)
}
else
if
(
cause
==
nas
::
EMmCause
::
N1_MODE_NOT_ALLOWED
)
{
m_storedGuti
=
{};
m_lastVisitedRegisteredTai
=
{};
m_taiList
=
{};
m_currentNsCtx
=
{};
m_nonCurrentNsCtx
=
{};
m_storage
.
discardUsim
();
switchMmState
(
EMmState
::
MM_NULL
,
EMmSubState
::
MM_NULL_NA
);
switchRmState
(
ERmState
::
RM_DEREGISTERED
);
...
...
src/ue/mm/security.cpp
View file @
31196a88
...
...
@@ -22,7 +22,7 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg)
m_logger
->
err
(
"Rejecting Security Mode Command with cause: %s"
,
nas
::
utils
::
EnumToString
(
cause
));
};
if
(
!
m_nonCurrentNsCtx
.
has_value
())
if
(
!
m_
storage
.
m_
nonCurrentNsCtx
.
has_value
())
{
reject
(
nas
::
EMmCause
::
MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE
);
return
;
...
...
@@ -58,7 +58,7 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg)
// Assign ABBA (if any)
if
(
msg
.
abba
.
has_value
())
m_nonCurrentNsCtx
->
keys
.
abba
=
msg
.
abba
->
rawData
.
copy
();
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
abba
=
msg
.
abba
->
rawData
.
copy
();
// Check selected algorithms
{
...
...
@@ -68,17 +68,17 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg)
}
// Assign selected algorithms to security context, and derive NAS keys
m_nonCurrentNsCtx
->
integrity
=
msg
.
selectedNasSecurityAlgorithms
.
integrity
;
m_nonCurrentNsCtx
->
ciphering
=
msg
.
selectedNasSecurityAlgorithms
.
ciphering
;
keys
::
DeriveNasKeys
(
*
m_nonCurrentNsCtx
);
m_
storage
.
m_
nonCurrentNsCtx
->
integrity
=
msg
.
selectedNasSecurityAlgorithms
.
integrity
;
m_
storage
.
m_
nonCurrentNsCtx
->
ciphering
=
msg
.
selectedNasSecurityAlgorithms
.
ciphering
;
keys
::
DeriveNasKeys
(
*
m_
storage
.
m_
nonCurrentNsCtx
);
m_logger
->
debug
(
"Derived kNasEnc[%s] kNasInt[%s]"
,
m_nonCurrentNsCtx
->
keys
.
kNasEnc
.
toHexString
().
c_str
(),
m_nonCurrentNsCtx
->
keys
.
kNasInt
.
toHexString
().
c_str
());
m_logger
->
debug
(
"Selected integrity[%d] ciphering[%d]"
,
(
int
)
m_nonCurrentNsCtx
->
integrity
,
(
int
)
m_nonCurrentNsCtx
->
ciphering
);
m_logger
->
debug
(
"Derived kNasEnc[%s] kNasInt[%s]"
,
m_
storage
.
m_
nonCurrentNsCtx
->
keys
.
kNasEnc
.
toHexString
().
c_str
(),
m_storage
.
m_nonCurrentNsCtx
->
keys
.
kNasInt
.
toHexString
().
c_str
());
m_logger
->
debug
(
"Selected integrity[%d] ciphering[%d]"
,
(
int
)
m_
storage
.
m_
nonCurrentNsCtx
->
integrity
,
(
int
)
m_
storage
.
m_
nonCurrentNsCtx
->
ciphering
);
// Set non-current NAS Security Context as current one.
m_
currentNsCtx
=
m_nonCurrentNsCtx
->
deepCopy
();
m_
storage
.
m_currentNsCtx
=
m_storage
.
m_nonCurrentNsCtx
->
deepCopy
();
// Prepare response
nas
::
SecurityModeComplete
resp
;
...
...
src/ue/mm/transport.cpp
View file @
31196a88
...
...
@@ -21,10 +21,11 @@ void NasMm::sendNasMessage(const nas::PlainMmMessage &msg)
// TODO trigger on send
OctetString
pdu
{};
if
(
m_currentNsCtx
.
has_value
()
&&
(
m_currentNsCtx
->
integrity
!=
nas
::
ETypeOfIntegrityProtectionAlgorithm
::
IA0
||
m_currentNsCtx
->
ciphering
!=
nas
::
ETypeOfCipheringAlgorithm
::
EA0
))
if
(
m_storage
.
m_currentNsCtx
.
has_value
()
&&
(
m_storage
.
m_currentNsCtx
->
integrity
!=
nas
::
ETypeOfIntegrityProtectionAlgorithm
::
IA0
||
m_storage
.
m_currentNsCtx
->
ciphering
!=
nas
::
ETypeOfCipheringAlgorithm
::
EA0
))
{
auto
secured
=
nas_enc
::
Encrypt
(
*
m_currentNsCtx
,
msg
);
auto
secured
=
nas_enc
::
Encrypt
(
*
m_
storage
.
m_
currentNsCtx
,
msg
);
nas
::
EncodeNasMessage
(
*
secured
,
pdu
);
}
else
...
...
@@ -62,7 +63,7 @@ void NasMm::receiveNasMessage(const nas::NasMessage &msg)
{
// If any NAS signalling message is received as not integrity protected even though the secure exchange of NAS
// messages has been established by the network, then the NAS shall discard this message
if
(
m_currentNsCtx
.
has_value
())
if
(
m_
storage
.
m_
currentNsCtx
.
has_value
())
{
m_logger
->
err
(
"Not integrity protected NAS message received after security establishment. Ignoring received "
...
...
@@ -100,14 +101,14 @@ void NasMm::receiveNasMessage(const nas::NasMessage &msg)
return
;
}
if
(
!
m_currentNsCtx
.
has_value
())
if
(
!
m_
storage
.
m_
currentNsCtx
.
has_value
())
{
m_logger
->
warn
(
"Secured NAS message received while no security context"
);
sendMmStatus
(
nas
::
EMmCause
::
MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE
);
return
;
}
auto
decrypted
=
nas_enc
::
Decrypt
(
*
m_currentNsCtx
,
securedMm
);
auto
decrypted
=
nas_enc
::
Decrypt
(
*
m_
storage
.
m_
currentNsCtx
,
securedMm
);
if
(
decrypted
==
nullptr
)
{
m_logger
->
err
(
"MAC mismatch in NAS encryption. Ignoring received NAS Message."
);
...
...
src/ue/nas/storage.cpp
0 → 100644
View file @
31196a88
//
// 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 "storage.hpp"
namespace
nr
::
ue
{
}
// namespace nr::ue
src/ue/nas/storage.hpp
0 → 100644
View file @
31196a88
//
// 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 <nas/nas.hpp>
#include <ue/types.hpp>
#pragma once
namespace
nr
::
ue
{
class
MobileStorage
{
private:
bool
m_simIsValid
{};
public:
// Location related
nas
::
IE5gsMobileIdentity
m_storedGuti
{};
std
::
optional
<
nas
::
IE5gsTrackingAreaIdentity
>
m_lastVisitedRegisteredTai
{};
E5UState
m_uState
{};
// Identity related
nas
::
IE5gsMobileIdentity
m_storedSuci
{};
// Plmn related
std
::
optional
<
nas
::
IE5gsTrackingAreaIdentityList
>
m_taiList
{};
// Security related
std
::
optional
<
NasSecurityContext
>
m_currentNsCtx
{};
std
::
optional
<
NasSecurityContext
>
m_nonCurrentNsCtx
{};
OctetString
m_sqn
{};
public:
void
initialize
(
bool
hasSupi
)
{
m_simIsValid
=
hasSupi
;
}
void
discardLocation
()
{
m_storedGuti
=
{};
m_lastVisitedRegisteredTai
=
{};
}
void
discardPlmn
()
{
m_taiList
=
{};
}
void
discardSecurity
()
{
m_currentNsCtx
=
{};
m_nonCurrentNsCtx
=
{};
}
void
discardCurrentSecurity
()
{
m_currentNsCtx
=
{};
// normally NON-current nsCtx is not stored in USIM
}
void
discardUsim
()
{
discardLocation
();
discardPlmn
();
discardSecurity
();
}
void
invalidateSim
()
{
// TODO: log
discardUsim
();
m_simIsValid
=
false
;
}
[[
nodiscard
]]
bool
isSimValid
()
const
{
return
m_simIsValid
;
}
};
}
// namespace nr::ue
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment