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
ebb486fb
Commit
ebb486fb
authored
Feb 24, 2021
by
aligungr
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Security mode control improvements
parent
faff949c
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
108 additions
and
42 deletions
+108
-42
src/ue/mm/auth.cpp
src/ue/mm/auth.cpp
+2
-2
src/ue/mm/base.cpp
src/ue/mm/base.cpp
+1
-1
src/ue/mm/dereg.cpp
src/ue/mm/dereg.cpp
+1
-1
src/ue/mm/register.cpp
src/ue/mm/register.cpp
+2
-2
src/ue/mm/security.cpp
src/ue/mm/security.cpp
+96
-31
src/ue/mm/transport.cpp
src/ue/mm/transport.cpp
+3
-3
src/ue/nas/storage.hpp
src/ue/nas/storage.hpp
+3
-2
No files found.
src/ue/mm/auth.cpp
View file @
ebb486fb
...
@@ -188,7 +188,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms
...
@@ -188,7 +188,7 @@ void NasMm::receiveAuthenticationRequestEap(const nas::AuthenticationRequest &ms
auto
kAusf
=
keys
::
CalculateKAusfForEapAkaPrime
(
mk
);
auto
kAusf
=
keys
::
CalculateKAusfForEapAkaPrime
(
mk
);
m_logger
->
debug
(
"kAusf: %s"
,
kAusf
.
toHexString
().
c_str
());
m_logger
->
debug
(
"kAusf: %s"
,
kAusf
.
toHexString
().
c_str
());
m_storage
.
m_nonCurrentNsCtx
=
NasSecurityContext
{}
;
m_storage
.
m_nonCurrentNsCtx
=
std
::
make_unique
<
NasSecurityContext
>
()
;
m_storage
.
m_nonCurrentNsCtx
->
tsc
=
msg
.
ngKSI
.
tsc
;
m_storage
.
m_nonCurrentNsCtx
->
tsc
=
msg
.
ngKSI
.
tsc
;
m_storage
.
m_nonCurrentNsCtx
->
ngKsi
=
msg
.
ngKSI
.
ksi
;
m_storage
.
m_nonCurrentNsCtx
->
ngKsi
=
msg
.
ngKSI
.
ksi
;
m_storage
.
m_nonCurrentNsCtx
->
keys
.
rand
=
std
::
move
(
receivedRand
);
m_storage
.
m_nonCurrentNsCtx
->
keys
.
rand
=
std
::
move
(
receivedRand
);
...
@@ -277,7 +277,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &
...
@@ -277,7 +277,7 @@ void NasMm::receiveAuthenticationRequest5gAka(const nas::AuthenticationRequest &
if
(
IGNORE_CONTROLS_FAILURES
||
autnCheck
==
EAutnValidationRes
::
OK
)
if
(
IGNORE_CONTROLS_FAILURES
||
autnCheck
==
EAutnValidationRes
::
OK
)
{
{
// 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_storage
.
m_nonCurrentNsCtx
=
NasSecurityContext
{}
;
m_storage
.
m_nonCurrentNsCtx
=
std
::
make_unique
<
NasSecurityContext
>
()
;
m_storage
.
m_nonCurrentNsCtx
->
tsc
=
msg
.
ngKSI
.
tsc
;
m_storage
.
m_nonCurrentNsCtx
->
tsc
=
msg
.
ngKSI
.
tsc
;
m_storage
.
m_nonCurrentNsCtx
->
ngKsi
=
msg
.
ngKSI
.
ksi
;
m_storage
.
m_nonCurrentNsCtx
->
ngKsi
=
msg
.
ngKSI
.
ksi
;
m_storage
.
m_nonCurrentNsCtx
->
keys
.
rand
=
rand
.
copy
();
m_storage
.
m_nonCurrentNsCtx
->
keys
.
rand
=
rand
.
copy
();
...
...
src/ue/mm/base.cpp
View file @
ebb486fb
...
@@ -192,7 +192,7 @@ void NasMm::onSwitchMmState(EMmState oldState, EMmState newState, EMmSubState ol
...
@@ -192,7 +192,7 @@ void NasMm::onSwitchMmState(EMmState oldState, EMmState newState, EMmSubState ol
// 5GMM-DEREGISTERED for any other state except 5GMM-NULL.
// 5GMM-DEREGISTERED for any other state except 5GMM-NULL.
if
(
oldState
==
EMmState
::
MM_DEREGISTERED
&&
newState
!=
EMmState
::
MM_DEREGISTERED
&&
newState
!=
EMmState
::
MM_NULL
)
if
(
oldState
==
EMmState
::
MM_DEREGISTERED
&&
newState
!=
EMmState
::
MM_DEREGISTERED
&&
newState
!=
EMmState
::
MM_NULL
)
{
{
if
(
m_storage
.
m_currentNsCtx
.
has_value
()
||
m_storage
.
m_nonCurrentNsCtx
.
has_value
()
)
if
(
m_storage
.
m_currentNsCtx
||
m_storage
.
m_nonCurrentNsCtx
)
{
{
m_logger
->
debug
(
"Deleting NAS security context"
);
m_logger
->
debug
(
"Deleting NAS security context"
);
...
...
src/ue/mm/dereg.cpp
View file @
ebb486fb
...
@@ -30,7 +30,7 @@ void NasMm::sendDeregistration(nas::ESwitchOff switchOff, bool dueToDisable5g)
...
@@ -30,7 +30,7 @@ void NasMm::sendDeregistration(nas::ESwitchOff switchOff, bool dueToDisable5g)
request
->
deRegistrationType
.
reRegistrationRequired
=
nas
::
EReRegistrationRequired
::
NOT_REQUIRED
;
request
->
deRegistrationType
.
reRegistrationRequired
=
nas
::
EReRegistrationRequired
::
NOT_REQUIRED
;
request
->
deRegistrationType
.
switchOff
=
switchOff
;
request
->
deRegistrationType
.
switchOff
=
switchOff
;
if
(
m_storage
.
m_currentNsCtx
.
has_value
()
)
if
(
m_storage
.
m_currentNsCtx
)
{
{
request
->
ngKSI
.
tsc
=
m_storage
.
m_currentNsCtx
->
tsc
;
request
->
ngKSI
.
tsc
=
m_storage
.
m_currentNsCtx
->
tsc
;
request
->
ngKSI
.
ksi
=
m_storage
.
m_currentNsCtx
->
ngKsi
;
request
->
ngKSI
.
ksi
=
m_storage
.
m_currentNsCtx
->
ngKsi
;
...
...
src/ue/mm/register.cpp
View file @
ebb486fb
...
@@ -29,9 +29,9 @@ void NasMm::sendRegistration(nas::ERegistrationType registrationType, nas::EFoll
...
@@ -29,9 +29,9 @@ void NasMm::sendRegistration(nas::ERegistrationType registrationType, nas::EFoll
switchMmState
(
EMmState
::
MM_REGISTERED_INITIATED
,
EMmSubState
::
MM_REGISTERED_INITIATED_NA
);
switchMmState
(
EMmState
::
MM_REGISTERED_INITIATED
,
EMmSubState
::
MM_REGISTERED_INITIATED_NA
);
nas
::
IENasKeySetIdentifier
ngKsi
;
nas
::
IENasKeySetIdentifier
ngKsi
{}
;
if
(
m_storage
.
m_currentNsCtx
.
has_value
()
)
if
(
m_storage
.
m_currentNsCtx
)
{
{
ngKsi
.
tsc
=
m_storage
.
m_currentNsCtx
->
tsc
;
ngKsi
.
tsc
=
m_storage
.
m_currentNsCtx
->
tsc
;
ngKsi
.
ksi
=
m_storage
.
m_currentNsCtx
->
ngKsi
;
ngKsi
.
ksi
=
m_storage
.
m_currentNsCtx
->
ngKsi
;
...
...
src/ue/mm/security.cpp
View file @
ebb486fb
...
@@ -13,8 +13,26 @@
...
@@ -13,8 +13,26 @@
namespace
nr
::
ue
namespace
nr
::
ue
{
{
static
bool
IsValidKsi
(
const
nas
::
IENasKeySetIdentifier
&
ngKsi
)
{
return
ngKsi
.
tsc
==
nas
::
ETypeOfSecurityContext
::
NATIVE_SECURITY_CONTEXT
&&
ngKsi
.
ksi
!=
nas
::
IENasKeySetIdentifier
::
NOT_AVAILABLE_OR_RESERVED
;
}
static
int
FindSecurityContext
(
int
ksi
,
const
std
::
unique_ptr
<
NasSecurityContext
>
&
current
,
const
std
::
unique_ptr
<
NasSecurityContext
>
&
nonCurrent
)
{
if
(
current
!=
nullptr
&&
current
->
ngKsi
==
ksi
)
return
0
;
if
(
nonCurrent
!=
nullptr
&&
nonCurrent
->
ngKsi
==
ksi
)
return
1
;
return
-
1
;
}
void
NasMm
::
receiveSecurityModeCommand
(
const
nas
::
SecurityModeCommand
&
msg
)
void
NasMm
::
receiveSecurityModeCommand
(
const
nas
::
SecurityModeCommand
&
msg
)
{
{
m_logger
->
debug
(
"Security Mode Command received"
);
auto
reject
=
[
this
](
nas
::
EMmCause
cause
)
{
auto
reject
=
[
this
](
nas
::
EMmCause
cause
)
{
nas
::
SecurityModeReject
resp
;
nas
::
SecurityModeReject
resp
;
resp
.
mmCause
.
value
=
cause
;
resp
.
mmCause
.
value
=
cause
;
...
@@ -22,65 +40,110 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg)
...
@@ -22,65 +40,110 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg)
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
));
};
};
if
(
!
m_storage
.
m_nonCurrentNsCtx
.
has_value
())
// ============================== Check the received ngKSI ==============================
if
(
!
IsValidKsi
(
msg
.
ngKsi
))
{
{
reject
(
nas
::
EMmCause
::
MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE
);
m_logger
->
err
(
"Invalid ngKSI received, tsc[%d], ksi[%d]"
,
(
int
)
msg
.
ngKsi
.
tsc
,
msg
.
ngKsi
.
ksi
);
reject
(
nas
::
EMmCause
::
SEC_MODE_REJECTED_UNSPECIFIED
);
return
;
return
;
}
}
// TODO: check the integrity with new security context
if
(
msg
.
ngKsi
.
ksi
==
0
&&
msg
.
selectedNasSecurityAlgorithms
.
integrity
==
nas
::
ETypeOfIntegrityProtectionAlgorithm
::
IA0
&&
msg
.
selectedNasSecurityAlgorithms
.
ciphering
==
nas
::
ETypeOfCipheringAlgorithm
::
EA0
)
{
// TODO
}
int
whichCtx
=
FindSecurityContext
(
msg
.
ngKsi
.
ksi
,
m_storage
.
m_currentNsCtx
,
m_storage
.
m_nonCurrentNsCtx
);
if
(
whichCtx
==
-
1
)
{
{
m_logger
->
err
(
"Security context with ngKSI[%d] not found"
,
msg
.
ngKsi
.
ksi
);
reject
(
nas
::
EMmCause
::
SEC_MODE_REJECTED_UNSPECIFIED
);
return
;
}
auto
&
nsCtx
=
whichCtx
==
0
?
m_storage
.
m_currentNsCtx
:
m_storage
.
m_nonCurrentNsCtx
;
// ======================== Check the integrity with new security context ========================
{
// TODO:
octet4
mac
=
msg
.
_macForNewSC
;
octet4
mac
=
msg
.
_macForNewSC
;
(
void
)
mac
;
(
void
)
mac
;
}
}
// Check replayed UE security capabilities
// ======================== Check replayed UE security capabilities ========================
if
(
!
nas
::
utils
::
DeepEqualsIe
(
msg
.
replayedUeSecurityCapabilities
,
createSecurityCapabilityIe
()))
{
m_logger
->
err
(
"Replayed UE security capability mismatch"
);
reject
(
nas
::
EMmCause
::
UE_SECURITY_CAP_MISMATCH
);
return
;
}
// ======================== Check selected NAS security algorithms ========================
{
{
auto
&
replayed
=
msg
.
replayedUeSecurityCapabilities
;
auto
integrity
=
msg
.
selectedNasSecurityAlgorithms
.
integrity
;
auto
real
=
createSecurityCapabilityIe
()
;
auto
ciphering
=
msg
.
selectedNasSecurityAlgorithms
.
ciphering
;
if
(
!
nas
::
utils
::
DeepEqualsIe
(
replayed
,
real
))
if
(
integrity
>
nas
::
ETypeOfIntegrityProtectionAlgorithm
::
IA3_128
||
ciphering
>
nas
::
ETypeOfCipheringAlgorithm
::
EA3_128
)
{
{
m_logger
->
err
(
"Selected NAS security algorithms are invalid"
);
reject
(
nas
::
EMmCause
::
UE_SECURITY_CAP_MISMATCH
);
reject
(
nas
::
EMmCause
::
UE_SECURITY_CAP_MISMATCH
);
return
;
return
;
}
}
}
}
// Handle EAP-Success message if any.
// ============================ Process the security context. ============================
if
(
msg
.
eapMessage
.
has_value
())
{
if
(
msg
.
eapMessage
->
eap
->
code
==
eap
::
ECode
::
SUCCESS
)
receiveEapSuccessMessage
(
*
msg
.
eapMessage
->
eap
);
else
m_logger
->
warn
(
"EAP message with inconvenient code received in Security Mode Command. Ignoring EAP message."
);
}
// Assign ABBA (if any)
// Assign ABBA (if any)
if
(
msg
.
abba
.
has_value
())
if
(
msg
.
abba
.
has_value
())
m_storage
.
m_nonCurrentN
sCtx
->
keys
.
abba
=
msg
.
abba
->
rawData
.
copy
();
n
sCtx
->
keys
.
abba
=
msg
.
abba
->
rawData
.
copy
();
// Check selected algorithms
// Assign selected algorithms to security context, and derive NAS keys
nsCtx
->
integrity
=
msg
.
selectedNasSecurityAlgorithms
.
integrity
;
nsCtx
->
ciphering
=
msg
.
selectedNasSecurityAlgorithms
.
ciphering
;
keys
::
DeriveNasKeys
(
*
nsCtx
);
m_logger
->
debug
(
"Derived kNasEnc[%s] kNasInt[%s]"
,
nsCtx
->
keys
.
kNasEnc
.
toHexString
().
c_str
(),
nsCtx
->
keys
.
kNasInt
.
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
// 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.
{
nsCtx
->
uplinkCount
.
sqn
=
0
;
nsCtx
->
uplinkCount
.
overflow
=
octet2
{
0
};
}
if
(
msg
.
selectedNasSecurityAlgorithms
.
integrity
!=
nas
::
ETypeOfIntegrityProtectionAlgorithm
::
IA0
)
{
{
// TODO
// TODO
// if (msg.selectedNasSecurityAlgorithms.integrity is supported according to config file)
// if (msg.selectedNasSecurityAlgorithms.ciphering is supported according to config file)
}
}
// Assign selected algorithms to security context, and derive NAS keys
// Set the new NAS Security Context as current one. (If it is not already the current one)
m_storage
.
m_nonCurrentNsCtx
->
integrity
=
msg
.
selectedNasSecurityAlgorithms
.
integrity
;
if
(
whichCtx
==
1
)
m_storage
.
m_nonCurrentNsCtx
->
ciphering
=
msg
.
selectedNasSecurityAlgorithms
.
ciphering
;
m_storage
.
m_currentNsCtx
=
std
::
make_unique
<
NasSecurityContext
>
(
nsCtx
->
deepCopy
());
keys
::
DeriveNasKeys
(
*
m_storage
.
m_nonCurrentNsCtx
);
// ============================ Handle EAP-Success message if any. ============================
m_logger
->
debug
(
"Derived kNasEnc[%s] kNasInt[%s]"
,
m_storage
.
m_nonCurrentNsCtx
->
keys
.
kNasEnc
.
toHexString
().
c_str
(),
if
(
msg
.
eapMessage
.
has_value
())
m_storage
.
m_nonCurrentNsCtx
->
keys
.
kNasInt
.
toHexString
().
c_str
());
{
m_logger
->
debug
(
"Selected integrity[%d] ciphering[%d]"
,
(
int
)
m_storage
.
m_nonCurrentNsCtx
->
integrity
,
if
(
msg
.
eapMessage
->
eap
->
code
==
eap
::
ECode
::
SUCCESS
)
(
int
)
m_storage
.
m_nonCurrentNsCtx
->
ciphering
);
receiveEapSuccessMessage
(
*
msg
.
eapMessage
->
eap
);
else
m_logger
->
warn
(
"EAP message with inconvenient code received in Security Mode Command. Ignoring EAP message."
);
}
// Set non-current NAS Security Context as current one.
// ============================ Send the Security Mode Complete. ============================
m_storage
.
m_currentNsCtx
=
m_storage
.
m_nonCurrentNsCtx
->
deepCopy
();
// Prepare response
nas
::
SecurityModeComplete
resp
{};
nas
::
SecurityModeComplete
resp
{};
// Append IMEISV if requested
// Append IMEISV if requested
...
@@ -94,6 +157,8 @@ void NasMm::receiveSecurityModeCommand(const nas::SecurityModeCommand &msg)
...
@@ -94,6 +157,8 @@ 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
{};
resp
.
nasMessageContainer
=
nas
::
IENasMessageContainer
{};
nas
::
EncodeNasMessage
(
*
m_lastRegistrationRequest
,
resp
.
nasMessageContainer
->
data
);
nas
::
EncodeNasMessage
(
*
m_lastRegistrationRequest
,
resp
.
nasMessageContainer
->
data
);
...
...
src/ue/mm/transport.cpp
View file @
ebb486fb
...
@@ -21,7 +21,7 @@ void NasMm::sendNasMessage(const nas::PlainMmMessage &msg)
...
@@ -21,7 +21,7 @@ void NasMm::sendNasMessage(const nas::PlainMmMessage &msg)
// TODO trigger on send
// TODO trigger on send
OctetString
pdu
{};
OctetString
pdu
{};
if
(
m_storage
.
m_currentNsCtx
.
has_value
()
&&
if
(
m_storage
.
m_currentNsCtx
&&
(
m_storage
.
m_currentNsCtx
->
integrity
!=
nas
::
ETypeOfIntegrityProtectionAlgorithm
::
IA0
||
(
m_storage
.
m_currentNsCtx
->
integrity
!=
nas
::
ETypeOfIntegrityProtectionAlgorithm
::
IA0
||
m_storage
.
m_currentNsCtx
->
ciphering
!=
nas
::
ETypeOfCipheringAlgorithm
::
EA0
))
m_storage
.
m_currentNsCtx
->
ciphering
!=
nas
::
ETypeOfCipheringAlgorithm
::
EA0
))
{
{
...
@@ -63,7 +63,7 @@ void NasMm::receiveNasMessage(const nas::NasMessage &msg)
...
@@ -63,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
// 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
// messages has been established by the network, then the NAS shall discard this message
if
(
m_storage
.
m_currentNsCtx
.
has_value
()
)
if
(
m_storage
.
m_currentNsCtx
)
{
{
m_logger
->
err
(
m_logger
->
err
(
"Not integrity protected NAS message received after security establishment. Ignoring received "
"Not integrity protected NAS message received after security establishment. Ignoring received "
...
@@ -101,7 +101,7 @@ void NasMm::receiveNasMessage(const nas::NasMessage &msg)
...
@@ -101,7 +101,7 @@ void NasMm::receiveNasMessage(const nas::NasMessage &msg)
return
;
return
;
}
}
if
(
!
m_storage
.
m_currentNsCtx
.
has_value
()
)
if
(
!
m_storage
.
m_currentNsCtx
)
{
{
m_logger
->
warn
(
"Secured NAS message received while no security context"
);
m_logger
->
warn
(
"Secured NAS message received while no security context"
);
sendMmStatus
(
nas
::
EMmCause
::
MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE
);
sendMmStatus
(
nas
::
EMmCause
::
MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE
);
...
...
src/ue/nas/storage.hpp
View file @
ebb486fb
...
@@ -35,8 +35,8 @@ class MobileStorage
...
@@ -35,8 +35,8 @@ class MobileStorage
nas
::
IEPlmnList
m_forbiddenPlmnList
{};
nas
::
IEPlmnList
m_forbiddenPlmnList
{};
// Security related
// Security related
std
::
optional
<
NasSecurityContext
>
m_currentNsCtx
{};
std
::
unique_ptr
<
NasSecurityContext
>
m_currentNsCtx
{};
std
::
optional
<
NasSecurityContext
>
m_nonCurrentNsCtx
{};
std
::
unique_ptr
<
NasSecurityContext
>
m_nonCurrentNsCtx
{};
OctetString
m_sqn
{};
OctetString
m_sqn
{};
public:
public:
...
@@ -75,6 +75,7 @@ class MobileStorage
...
@@ -75,6 +75,7 @@ class MobileStorage
discardSecurity
();
discardSecurity
();
}
}
// todo metodları kaldır geri
void
invalidateSim__
()
void
invalidateSim__
()
{
{
// TODO: log
// TODO: log
...
...
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