Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
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
spbro
OpenXG-RAN
Commits
64f55693
Commit
64f55693
authored
Jun 13, 2024
by
Jaroslava Fiedlerova
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/nrue-nas-security' into integration_2024_w24
parents
4d51b344
fc42a2a5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
298 additions
and
103 deletions
+298
-103
openair3/NAS/NR_UE/nr_nas_msg_sim.c
openair3/NAS/NR_UE/nr_nas_msg_sim.c
+263
-73
openair3/NAS/NR_UE/nr_nas_msg_sim.h
openair3/NAS/NR_UE/nr_nas_msg_sim.h
+3
-2
openair3/SECU/nas_stream_eia1.c
openair3/SECU/nas_stream_eia1.c
+32
-28
No files found.
openair3/NAS/NR_UE/nr_nas_msg_sim.c
View file @
64f55693
...
...
@@ -58,6 +58,79 @@ extern uint16_t NB_UE_INST;
static
nr_ue_nas_t
nr_ue_nas
=
{
0
};
static
nr_nas_msg_snssai_t
nas_allowed_nssai
[
8
];
typedef
enum
{
NAS_SECURITY_NO_SECURITY_CONTEXT
,
NAS_SECURITY_UNPROTECTED
,
NAS_SECURITY_INTEGRITY_FAILED
,
NAS_SECURITY_INTEGRITY_PASSED
,
NAS_SECURITY_BAD_INPUT
}
security_state_t
;
security_state_t
nas_security_rx_process
(
nr_ue_nas_t
*
nas
,
uint8_t
*
pdu_buffer
,
int
pdu_length
)
{
if
(
nas
->
security_container
==
NULL
)
return
NAS_SECURITY_NO_SECURITY_CONTEXT
;
if
(
pdu_buffer
[
1
]
==
0
)
return
NAS_SECURITY_UNPROTECTED
;
/* header is 7 bytes, require at least one byte of payload */
if
(
pdu_length
<
8
)
return
NAS_SECURITY_BAD_INPUT
;
/* only accept "integrity protected and ciphered" messages */
if
(
pdu_buffer
[
1
]
!=
2
)
{
LOG_E
(
NAS
,
"todo: unhandled security type %d
\n
"
,
pdu_buffer
[
2
]);
return
NAS_SECURITY_BAD_INPUT
;
}
/* synchronize NAS SQN, based on 24.501 4.4.3.1 */
int
nas_sqn
=
pdu_buffer
[
6
];
int
target_sqn
=
nas
->
security
.
nas_count_dl
&
0xff
;
if
(
nas_sqn
!=
target_sqn
)
{
if
(
nas_sqn
<
target_sqn
)
nas
->
security
.
nas_count_dl
+=
256
;
nas
->
security
.
nas_count_dl
&=
~
255
;
nas
->
security
.
nas_count_dl
|=
nas_sqn
;
}
if
(
nas
->
security
.
nas_count_dl
>
0x00ffffff
)
{
/* it's doubtful that this will happen, so let's simply exit for the time being */
/* to be refined if needed */
LOG_E
(
NAS
,
"max NAS COUNT DL reached
\n
"
);
exit
(
1
);
}
/* check integrity */
uint8_t
computed_mac
[
4
];
nas_stream_cipher_t
stream_cipher
;
stream_cipher
.
context
=
nas
->
security_container
->
integrity_context
;
stream_cipher
.
count
=
nas
->
security
.
nas_count_dl
;
stream_cipher
.
bearer
=
1
;
/* todo: don't hardcode */
stream_cipher
.
direction
=
1
;
stream_cipher
.
message
=
pdu_buffer
+
6
;
/* length in bits */
stream_cipher
.
blength
=
(
pdu_length
-
6
)
<<
3
;
stream_compute_integrity
(
nas
->
security_container
->
integrity_algorithm
,
&
stream_cipher
,
computed_mac
);
uint8_t
*
received_mac
=
pdu_buffer
+
2
;
if
(
memcmp
(
received_mac
,
computed_mac
,
4
)
!=
0
)
return
NAS_SECURITY_INTEGRITY_FAILED
;
/* decipher */
uint8_t
buf
[
pdu_length
-
7
];
stream_cipher
.
context
=
nas
->
security_container
->
ciphering_context
;
stream_cipher
.
count
=
nas
->
security
.
nas_count_dl
;
stream_cipher
.
bearer
=
1
;
/* todo: don't hardcode */
stream_cipher
.
direction
=
1
;
stream_cipher
.
message
=
pdu_buffer
+
7
;
/* length in bits */
stream_cipher
.
blength
=
(
pdu_length
-
7
)
<<
3
;
stream_compute_encrypt
(
nas
->
security_container
->
ciphering_algorithm
,
&
stream_cipher
,
buf
);
memcpy
(
pdu_buffer
+
7
,
buf
,
pdu_length
-
7
);
nas
->
security
.
nas_count_dl
++
;
return
NAS_SECURITY_INTEGRITY_PASSED
;
}
static
int
nas_protected_security_header_encode
(
char
*
buffer
,
const
fgs_nas_message_security_header_t
*
header
,
...
...
@@ -301,7 +374,8 @@ void derive_kamf(uint8_t *kseaf, uint8_t *kamf, uint16_t abba, uicc_t* uicc) {
}
//------------------------------------------------------------------------------
void
derive_knas
(
algorithm_type_dist_t
nas_alg_type
,
uint8_t
nas_alg_id
,
uint8_t
kamf
[
32
],
uint8_t
*
knas_int
)
{
void
derive_knas
(
algorithm_type_dist_t
nas_alg_type
,
uint8_t
nas_alg_id
,
uint8_t
kamf
[
32
],
uint8_t
*
knas
)
{
uint8_t
S
[
20
]
=
{
0
};
uint8_t
out
[
32
]
=
{
0
};
S
[
0
]
=
0x69
;
//FC
...
...
@@ -315,7 +389,7 @@ void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t
byte_array_t
data
=
{.
buf
=
S
,
.
len
=
7
};
kdf
(
kamf
,
data
,
32
,
out
);
memcpy
(
knas
_int
,
out
+
16
,
16
);
memcpy
(
knas
,
out
+
16
,
16
);
}
void
derive_kgnb
(
uint8_t
kamf
[
32
],
uint32_t
count
,
uint8_t
*
kgnb
){
...
...
@@ -360,7 +434,6 @@ void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) {
uint8_t
*
kausf
=
nas
->
security
.
kausf
;
uint8_t
*
kseaf
=
nas
->
security
.
kseaf
;
uint8_t
*
kamf
=
nas
->
security
.
kamf
;
uint8_t
*
knas_int
=
nas
->
security
.
knas_int
;
uint8_t
*
output
=
nas
->
security
.
res
;
uint8_t
*
rand
=
nas
->
security
.
rand
;
uint8_t
*
kgnb
=
nas
->
security
.
kgnb
;
...
...
@@ -383,7 +456,6 @@ void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) {
derive_kausf
(
ck
,
ik
,
sqn
,
kausf
,
nas
->
uicc
);
derive_kseaf
(
kausf
,
kseaf
,
nas
->
uicc
);
derive_kamf
(
kseaf
,
kamf
,
0x0000
,
nas
->
uicc
);
derive_knas
(
0x02
,
2
,
kamf
,
knas_int
);
derive_kgnb
(
kamf
,
0
,
kgnb
);
printf
(
"kausf:"
);
...
...
@@ -404,12 +476,6 @@ void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) {
printf
(
"%x "
,
kamf
[
i
]);
}
printf
(
"
\n
"
);
printf
(
"knas_int:
\n
"
);
for
(
int
i
=
0
;
i
<
16
;
i
++
){
printf
(
"%x "
,
knas_int
[
i
]);
}
printf
(
"
\n
"
);
}
nr_ue_nas_t
*
get_ue_nas_info
(
module_id_t
module_id
)
...
...
@@ -464,8 +530,8 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas)
mm_msg
->
registration_request
.
presencemask
|=
REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT
;
mm_msg
->
registration_request
.
nruesecuritycapability
.
iei
=
REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI
;
mm_msg
->
registration_request
.
nruesecuritycapability
.
length
=
8
;
mm_msg
->
registration_request
.
nruesecuritycapability
.
fg_EA
=
0x
a
0
;
mm_msg
->
registration_request
.
nruesecuritycapability
.
fg_IA
=
0x
2
0
;
mm_msg
->
registration_request
.
nruesecuritycapability
.
fg_EA
=
0x
e
0
;
mm_msg
->
registration_request
.
nruesecuritycapability
.
fg_IA
=
0x
6
0
;
mm_msg
->
registration_request
.
nruesecuritycapability
.
EEA
=
0
;
mm_msg
->
registration_request
.
nruesecuritycapability
.
EIA
=
0
;
size
+=
10
;
...
...
@@ -513,10 +579,6 @@ void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype
static
void
generateAuthenticationResp
(
nr_ue_nas_t
*
nas
,
as_nas_info_t
*
initialNasMsg
,
uint8_t
*
buf
)
{
derive_ue_keys
(
buf
,
nas
);
/* todo: as of now, nia2 is hardcoded in derive_ue_keys(), remove this hardcoding, use NAS signalling for getting proper algorithm */
/* todo: deal with ciphering for this stream_security_container_init() (handle ciphering in general) */
/* todo: stream_security_container_delete() is not called anywhere, deal with that */
nas
->
security_container
=
stream_security_container_init
(
0
,
2
/* hardcoded: nia2 */
,
NULL
,
nas
->
security
.
knas_int
);
OctetString
res
;
res
.
length
=
16
;
res
.
value
=
calloc
(
1
,
16
);
...
...
@@ -570,6 +632,7 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
// set security protected header
nas_msg
.
header
.
protocol_discriminator
=
FGS_MOBILITY_MANAGEMENT_MESSAGE
;
nas_msg
.
header
.
security_header_type
=
INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX
;
nas_msg
.
header
.
sequence_number
=
nas
->
security
.
nas_count_ul
&
0xff
;
size
+=
7
;
mm_msg
=
&
nas_msg
.
security_protected
.
plain
.
mm_msg
;
...
...
@@ -600,16 +663,29 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
initialNasMsg
->
length
=
security_header_len
+
mm_msg_encode
(
mm_msg
,
(
uint8_t
*
)(
initialNasMsg
->
data
+
security_header_len
),
size
-
security_header_len
);
/* ciphering */
uint8_t
buf
[
initialNasMsg
->
length
-
7
];
stream_cipher
.
context
=
nas
->
security_container
->
ciphering_context
;
AssertFatal
(
nas
->
security
.
nas_count_ul
<=
0xffffff
,
"fatal: NAS COUNT UL too big (todo: fix that)
\n
"
);
stream_cipher
.
count
=
nas
->
security
.
nas_count_ul
;
stream_cipher
.
bearer
=
1
;
stream_cipher
.
direction
=
0
;
stream_cipher
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
7
);
/* length in bits */
stream_cipher
.
blength
=
(
initialNasMsg
->
length
-
7
)
<<
3
;
stream_compute_encrypt
(
nas
->
security_container
->
ciphering_algorithm
,
&
stream_cipher
,
buf
);
memcpy
(
stream_cipher
.
message
,
buf
,
initialNasMsg
->
length
-
7
);
/* integrity protection */
stream_cipher
.
context
=
nas
->
security_container
->
integrity_context
;
stream_cipher
.
count
=
nas
->
security
.
mm_counter
++
;
stream_cipher
.
count
=
nas
->
security
.
nas_count_ul
++
;
stream_cipher
.
bearer
=
1
;
stream_cipher
.
direction
=
0
;
stream_cipher
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
6
);
/* length in bits */
stream_cipher
.
blength
=
(
initialNasMsg
->
length
-
6
)
<<
3
;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
stream_compute_integrity
(
EIA2_128_ALG_ID
,
&
stream_cipher
,
mac
);
stream_compute_integrity
(
nas
->
security_container
->
integrity_algorithm
,
&
stream_cipher
,
mac
);
printf
(
"mac %x %x %x %x
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
]);
for
(
int
i
=
0
;
i
<
4
;
i
++
){
...
...
@@ -617,6 +693,40 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
}
}
static
void
handle_security_mode_command
(
instance_t
instance
,
nr_ue_nas_t
*
nas
,
as_nas_info_t
*
initialNasMsg
,
uint8_t
*
pdu
,
int
pdu_length
)
{
/* retrieve integrity and ciphering algorithms */
AssertFatal
(
pdu_length
>
10
,
"nas: bad pdu
\n
"
);
int
ciphering_algorithm
=
(
pdu
[
10
]
>>
4
)
&
0x0f
;
int
integrity_algorithm
=
pdu
[
10
]
&
0x0f
;
uint8_t
*
kamf
=
nas
->
security
.
kamf
;
uint8_t
*
knas_enc
=
nas
->
security
.
knas_enc
;
uint8_t
*
knas_int
=
nas
->
security
.
knas_int
;
/* derive keys */
derive_knas
(
0x01
,
ciphering_algorithm
,
kamf
,
knas_enc
);
derive_knas
(
0x02
,
integrity_algorithm
,
kamf
,
knas_int
);
printf
(
"knas_int: "
);
for
(
int
i
=
0
;
i
<
16
;
i
++
){
printf
(
"%x "
,
knas_int
[
i
]);
}
printf
(
"
\n
"
);
printf
(
"knas_enc: "
);
for
(
int
i
=
0
;
i
<
16
;
i
++
){
printf
(
"%x "
,
knas_enc
[
i
]);
}
printf
(
"
\n
"
);
/* todo: stream_security_container_delete() is not called anywhere, deal with that */
nas
->
security_container
=
stream_security_container_init
(
ciphering_algorithm
,
integrity_algorithm
,
knas_enc
,
knas_int
);
nas_itti_kgnb_refresh_req
(
instance
,
nas
->
security
.
kgnb
);
generateSecurityModeComplete
(
nas
,
initialNasMsg
);
}
static
void
decodeRegistrationAccept
(
const
uint8_t
*
buf
,
int
len
,
nr_ue_nas_t
*
nas
)
{
registration_accept_msg
reg_acc
=
{
0
};
...
...
@@ -656,7 +766,7 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
sp_msg
->
header
.
protocol_discriminator
=
FGS_MOBILITY_MANAGEMENT_MESSAGE
;
sp_msg
->
header
.
security_header_type
=
INTEGRITY_PROTECTED_AND_CIPHERED
;
sp_msg
->
header
.
message_authentication_code
=
0
;
sp_msg
->
header
.
sequence_number
=
1
;
sp_msg
->
header
.
sequence_number
=
nas
->
security
.
nas_count_ul
&
0xff
;
length
=
7
;
sp_msg
->
plain
.
mm_msg
.
registration_complete
.
protocoldiscriminator
=
FGS_MOBILITY_MANAGEMENT_MESSAGE
;
length
+=
1
;
...
...
@@ -672,6 +782,7 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
// encode the message
initialNasMsg
->
data
=
(
Byte_t
*
)
malloc
(
length
*
sizeof
(
Byte_t
));
initialNasMsg
->
length
=
length
;
/* Encode the first octet of the header (extended protocol discriminator) */
ENCODE_U8
(
initialNasMsg
->
data
+
size
,
sp_msg
->
header
.
protocol_discriminator
,
size
);
...
...
@@ -698,18 +809,29 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
if
(
sortransparentcontainer
)
{
encode_registration_complete
(
&
sp_msg
->
plain
.
mm_msg
.
registration_complete
,
initialNasMsg
->
data
+
size
,
length
-
size
);
}
initialNasMsg
->
length
=
length
;
/* ciphering */
uint8_t
buf
[
initialNasMsg
->
length
-
7
];
stream_cipher
.
context
=
nas
->
security_container
->
ciphering_context
;
AssertFatal
(
nas
->
security
.
nas_count_ul
<=
0xffffff
,
"fatal: NAS COUNT UL too big (todo: fix that)
\n
"
);
stream_cipher
.
count
=
nas
->
security
.
nas_count_ul
;
stream_cipher
.
bearer
=
1
;
stream_cipher
.
direction
=
0
;
stream_cipher
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
7
);
/* length in bits */
stream_cipher
.
blength
=
(
initialNasMsg
->
length
-
7
)
<<
3
;
stream_compute_encrypt
(
nas
->
security_container
->
ciphering_algorithm
,
&
stream_cipher
,
buf
);
memcpy
(
stream_cipher
.
message
,
buf
,
initialNasMsg
->
length
-
7
);
/* integrity protection */
stream_cipher
.
context
=
nas
->
security_container
->
integrity_context
;
stream_cipher
.
count
=
nas
->
security
.
mm_counter
++
;
stream_cipher
.
count
=
nas
->
security
.
nas_count_ul
++
;
stream_cipher
.
bearer
=
1
;
stream_cipher
.
direction
=
0
;
stream_cipher
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
6
);
/* length in bits */
stream_cipher
.
blength
=
(
initialNasMsg
->
length
-
6
)
<<
3
;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
stream_compute_integrity
(
EIA2_128_ALG_ID
,
&
stream_cipher
,
mac
);
stream_compute_integrity
(
nas
->
security_container
->
integrity_algorithm
,
&
stream_cipher
,
mac
);
printf
(
"mac %x %x %x %x
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
]);
for
(
int
i
=
0
;
i
<
4
;
i
++
){
...
...
@@ -738,7 +860,7 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi
sp_msg
->
header
.
protocol_discriminator
=
FGS_MOBILITY_MANAGEMENT_MESSAGE
;
sp_msg
->
header
.
security_header_type
=
INTEGRITY_PROTECTED_AND_CIPHERED
;
sp_msg
->
header
.
message_authentication_code
=
0
;
sp_msg
->
header
.
sequence_number
=
3
;
sp_msg
->
header
.
sequence_number
=
nas
->
security
.
nas_count_ul
&
0xff
;
int
size
=
sizeof
(
fgs_nas_message_security_header_t
);
fgs_deregistration_request_ue_originating_msg
*
dereg_req
=
&
sp_msg
->
plain
.
mm_msg
.
fgs_deregistration_request_ue_originating
;
...
...
@@ -761,19 +883,36 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi
initialNasMsg
->
length
=
security_header_len
+
mm_msg_encode
(
&
sp_msg
->
plain
.
mm_msg
,
(
uint8_t
*
)(
initialNasMsg
->
data
+
security_header_len
),
size
-
security_header_len
);
nas_stream_cipher_t
stream_cipher
=
{
.
context
=
nas
->
security_container
->
integrity_context
,
.
count
=
nas
->
security
.
mm_counter
++
,
.
bearer
=
1
,
.
direction
=
0
,
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
6
),
.
blength
=
(
initialNasMsg
->
length
-
6
)
<<
3
,
/* length in bits */
};
nas_stream_cipher_t
stream_cipher
;
/* ciphering */
uint8_t
buf
[
initialNasMsg
->
length
-
7
];
stream_cipher
.
context
=
nas
->
security_container
->
ciphering_context
;
AssertFatal
(
nas
->
security
.
nas_count_ul
<=
0xffffff
,
"fatal: NAS COUNT UL too big (todo: fix that)
\n
"
);
stream_cipher
.
count
=
nas
->
security
.
nas_count_ul
;
stream_cipher
.
bearer
=
1
;
stream_cipher
.
direction
=
0
;
stream_cipher
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
7
);
/* length in bits */
stream_cipher
.
blength
=
(
initialNasMsg
->
length
-
7
)
<<
3
;
stream_compute_encrypt
(
nas
->
security_container
->
ciphering_algorithm
,
&
stream_cipher
,
buf
);
memcpy
(
stream_cipher
.
message
,
buf
,
initialNasMsg
->
length
-
7
);
/* integrity protection */
stream_cipher
.
context
=
nas
->
security_container
->
integrity_context
;
stream_cipher
.
count
=
nas
->
security
.
nas_count_ul
++
;
stream_cipher
.
bearer
=
1
;
stream_cipher
.
direction
=
0
;
stream_cipher
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
6
);
/* length in bits */
stream_cipher
.
blength
=
(
initialNasMsg
->
length
-
6
)
<<
3
;
uint8_t
mac
[
4
];
nas_stream_encrypt_eia2
(
&
stream_cipher
,
mac
);
stream_compute_integrity
(
nas
->
security_container
->
integrity_algorithm
,
&
stream_cipher
,
mac
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
initialNasMsg
->
data
[
2
+
i
]
=
mac
[
i
];
printf
(
"mac %x %x %x %x
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
]);
for
(
int
i
=
0
;
i
<
4
;
i
++
){
initialNasMsg
->
data
[
2
+
i
]
=
mac
[
i
];
}
}
static
void
generatePduSessionEstablishRequest
(
nr_ue_nas_t
*
nas
,
as_nas_info_t
*
initialNasMsg
,
nas_pdu_session_req_t
*
pdu_req
)
...
...
@@ -800,7 +939,7 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
uint8_t
mac
[
4
];
nas_msg
.
header
.
protocol_discriminator
=
FGS_MOBILITY_MANAGEMENT_MESSAGE
;
nas_msg
.
header
.
security_header_type
=
INTEGRITY_PROTECTED_AND_CIPHERED
;
nas_msg
.
header
.
sequence_number
=
2
;
nas_msg
.
header
.
sequence_number
=
nas
->
security
.
nas_count_ul
&
0xff
;
size
+=
7
;
...
...
@@ -852,16 +991,28 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
initialNasMsg
->
length
=
security_header_len
+
mm_msg_encode
(
mm_msg
,
(
uint8_t
*
)(
initialNasMsg
->
data
+
security_header_len
),
size
-
security_header_len
);
/* ciphering */
uint8_t
buf
[
initialNasMsg
->
length
-
7
];
stream_cipher
.
context
=
nas
->
security_container
->
ciphering_context
;
AssertFatal
(
nas
->
security
.
nas_count_ul
<=
0xffffff
,
"fatal: NAS COUNT UL too big (todo: fix that)
\n
"
);
stream_cipher
.
count
=
nas
->
security
.
nas_count_ul
;
stream_cipher
.
bearer
=
1
;
stream_cipher
.
direction
=
0
;
stream_cipher
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
7
);
/* length in bits */
stream_cipher
.
blength
=
(
initialNasMsg
->
length
-
7
)
<<
3
;
stream_compute_encrypt
(
nas
->
security_container
->
ciphering_algorithm
,
&
stream_cipher
,
buf
);
memcpy
(
stream_cipher
.
message
,
buf
,
initialNasMsg
->
length
-
7
);
/* integrity protection */
stream_cipher
.
context
=
nas
->
security_container
->
integrity_context
;
stream_cipher
.
count
=
nas
->
security
.
mm_counter
++
;
stream_cipher
.
count
=
nas
->
security
.
nas_count_ul
++
;
stream_cipher
.
bearer
=
1
;
stream_cipher
.
direction
=
0
;
stream_cipher
.
message
=
(
unsigned
char
*
)(
initialNasMsg
->
data
+
6
);
/* length in bits */
stream_cipher
.
blength
=
(
initialNasMsg
->
length
-
6
)
<<
3
;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
stream_compute_integrity
(
EIA2_128_ALG_ID
,
&
stream_cipher
,
mac
);
stream_compute_integrity
(
nas
->
security_container
->
integrity_algorithm
,
&
stream_cipher
,
mac
);
printf
(
"mac %x %x %x %x
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
]);
for
(
int
i
=
0
;
i
<
4
;
i
++
){
...
...
@@ -870,30 +1021,41 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
}
uint8_t
get_msg_type
(
uint8_t
*
pdu_buffer
,
uint32_t
length
)
{
uint8_t
msg_type
=
0
;
uint8_t
offset
=
0
;
static
uint8_t
get_msg_type
(
uint8_t
*
pdu_buffer
,
uint32_t
length
)
{
if
(
pdu_buffer
==
NULL
)
goto
error
;
if
((
pdu_buffer
!=
NULL
)
&&
(
length
>
0
))
{
if
(((
nas_msg_header_t
*
)(
pdu_buffer
))
->
choice
.
security_protected_nas_msg_header_t
.
security_header_type
>
0
)
{
offset
+=
SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH
;
if
(
offset
<
length
)
{
msg_type
=
((
mm_msg_header_t
*
)(
pdu_buffer
+
offset
))
->
message_type
;
/* get security header type */
if
(
length
<
2
)
goto
error
;
if
(
msg_type
==
FGS_DOWNLINK_NAS_TRANSPORT
)
{
dl_nas_transport_t
tmp
;
memcpy
(
&
tmp
,
pdu_buffer
+
offset
,
sizeof
(
tmp
));
msg_type
=
tmp
.
sm_nas_msg_header
.
message_type
;
}
}
}
else
{
// plain 5GS NAS message
msg_type
=
((
nas_msg_header_t
*
)(
pdu_buffer
))
->
choice
.
plain_nas_msg_header
.
message_type
;
}
}
else
{
LOG_I
(
NAS
,
"[UE] Received invalid downlink message
\n
"
);
int
security_header_type
=
pdu_buffer
[
1
];
if
(
security_header_type
==
0
)
{
/* plain NAS message */
if
(
length
<
3
)
goto
error
;
return
pdu_buffer
[
2
];
}
if
(
length
<
10
)
goto
error
;
int
msg_type
=
pdu_buffer
[
9
];
if
(
msg_type
==
FGS_DOWNLINK_NAS_TRANSPORT
)
{
if
(
length
<
17
)
goto
error
;
msg_type
=
pdu_buffer
[
16
];
}
return
msg_type
;
error:
LOG_E
(
NAS
,
"[UE] Received invalid downlink message
\n
"
);
return
0
;
}
static
void
send_nas_uplink_data_req
(
instance_t
instance
,
const
as_nas_info_t
*
initial_nas_msg
)
...
...
@@ -998,11 +1160,13 @@ static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_b
case
0x15
:
// allowed NSSAI
length
=
*
pdu_buffer
++
;
parse_allowed_nssai
(
nssai
,
pdu_buffer
,
length
);
pdu_buffer
+=
length
;
break
;
default:
LOG_W
(
NAS
,
"This NAS IEI is not handled when extracting list of allowed NSSAI
\n
"
);
pdu_buffer
=
end
;
LOG_W
(
NAS
,
"This NAS IEI (0x%2.2x) is not handled when extracting list of allowed NSSAI
\n
"
,
type
);
length
=
*
pdu_buffer
++
;
pdu_buffer
+=
length
;
break
;
}
}
...
...
@@ -1135,13 +1299,23 @@ void *nas_nrue(void *args_p)
NAS_CONN_ESTABLI_CNF
(
msg_p
).
nasMsg
.
length
);
uint8_t
*
pdu_buffer
=
NAS_CONN_ESTABLI_CNF
(
msg_p
).
nasMsg
.
data
;
int
msg_type
=
get_msg_type
(
pdu_buffer
,
NAS_CONN_ESTABLI_CNF
(
msg_p
).
nasMsg
.
length
);
int
pdu_length
=
NAS_CONN_ESTABLI_CNF
(
msg_p
).
nasMsg
.
length
;
nr_ue_nas_t
*
nas
=
get_ue_nas_info
(
0
);
security_state_t
security_state
=
nas_security_rx_process
(
nas
,
pdu_buffer
,
pdu_length
);
if
(
security_state
!=
NAS_SECURITY_INTEGRITY_PASSED
&&
security_state
!=
NAS_SECURITY_NO_SECURITY_CONTEXT
)
{
LOG_E
(
NAS
,
"NAS integrity failed, discard incoming message
\n
"
);
break
;
}
int
msg_type
=
get_msg_type
(
pdu_buffer
,
pdu_length
);
if
(
msg_type
==
REGISTRATION_ACCEPT
)
{
nr_ue_nas_t
*
nas
=
get_ue_nas_info
(
0
);
handle_registration_accept
(
instance
,
nas
,
pdu_buffer
,
NAS_CONN_ESTABLI_CNF
(
msg_p
).
nasMsg
.
length
);
handle_registration_accept
(
instance
,
nas
,
pdu_buffer
,
pdu_length
);
}
else
if
(
msg_type
==
FGS_PDU_SESSION_ESTABLISHMENT_ACC
)
{
capture_pdu_session_establishment_accept_msg
(
pdu_buffer
,
NAS_CONN_ESTABLI_CNF
(
msg_p
).
nasMsg
.
length
);
capture_pdu_session_establishment_accept_msg
(
pdu_buffer
,
pdu_
length
);
}
break
;
...
...
@@ -1199,10 +1373,27 @@ void *nas_nrue(void *args_p)
NAS_DOWNLINK_DATA_IND
(
msg_p
).
nasMsg
.
length
,
NAS_DOWNLINK_DATA_IND
(
msg_p
).
nasMsg
.
data
);
as_nas_info_t
initialNasMsg
=
{
0
};
nr_ue_nas_t
*
nas
=
get_ue_nas_info
(
0
);
uint8_t
*
pdu_buffer
=
NAS_DOWNLINK_DATA_IND
(
msg_p
).
nasMsg
.
data
;
int
msg_type
=
get_msg_type
(
pdu_buffer
,
NAS_DOWNLINK_DATA_IND
(
msg_p
).
nasMsg
.
length
);
nr_ue_nas_t
*
nas
=
get_ue_nas_info
(
0
);
int
pdu_length
=
NAS_DOWNLINK_DATA_IND
(
msg_p
).
nasMsg
.
length
;
security_state_t
security_state
=
nas_security_rx_process
(
nas
,
pdu_buffer
,
pdu_length
);
/* special cases accepted without protection */
if
(
security_state
==
NAS_SECURITY_UNPROTECTED
)
{
int
msg_type
=
get_msg_type
(
pdu_buffer
,
pdu_length
);
/* for the moment, only FGS_DEREGISTRATION_ACCEPT is accepted */
if
(
msg_type
==
FGS_DEREGISTRATION_ACCEPT
)
security_state
=
NAS_SECURITY_INTEGRITY_PASSED
;
}
if
(
security_state
!=
NAS_SECURITY_INTEGRITY_PASSED
&&
security_state
!=
NAS_SECURITY_NO_SECURITY_CONTEXT
)
{
LOG_E
(
NAS
,
"NAS integrity failed, discard incoming message
\n
"
);
break
;
}
int
msg_type
=
get_msg_type
(
pdu_buffer
,
pdu_length
);
switch
(
msg_type
)
{
case
FGS_IDENTITY_REQUEST
:
...
...
@@ -1212,14 +1403,13 @@ void *nas_nrue(void *args_p)
generateAuthenticationResp
(
nas
,
&
initialNasMsg
,
pdu_buffer
);
break
;
case
FGS_SECURITY_MODE_COMMAND
:
nas_itti_kgnb_refresh_req
(
instance
,
nas
->
security
.
kgnb
);
generateSecurityModeComplete
(
nas
,
&
initialNasMsg
);
handle_security_mode_command
(
instance
,
nas
,
&
initialNasMsg
,
pdu_buffer
,
pdu_length
);
break
;
case
FGS_DOWNLINK_NAS_TRANSPORT
:
decodeDownlinkNASTransport
(
&
initialNasMsg
,
pdu_buffer
);
break
;
case
REGISTRATION_ACCEPT
:
handle_registration_accept
(
instance
,
nas
,
pdu_buffer
,
NAS_DOWNLINK_DATA_IND
(
msg_p
).
nasMsg
.
length
);
handle_registration_accept
(
instance
,
nas
,
pdu_buffer
,
pdu_
length
);
break
;
case
FGS_DEREGISTRATION_ACCEPT
:
LOG_I
(
NAS
,
"received deregistration accept
\n
"
);
...
...
openair3/NAS/NR_UE/nr_nas_msg_sim.h
View file @
64f55693
...
...
@@ -89,11 +89,12 @@ typedef struct {
uint8_t
kseaf
[
32
];
uint8_t
kamf
[
32
];
uint8_t
knas_int
[
16
];
uint8_t
knas_enc
[
16
];
uint8_t
res
[
16
];
uint8_t
rand
[
16
];
uint8_t
kgnb
[
32
];
uint32_t
mm_counter
;
uint32_t
sm_counter
;
uint32_t
nas_count_ul
;
uint32_t
nas_count_dl
;
}
ue_sa_security_key_t
;
typedef
struct
{
...
...
openair3/SECU/nas_stream_eia1.c
View file @
64f55693
...
...
@@ -88,25 +88,36 @@ static uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c)
return
result
;
}
/*
mask32bit.
* Input n: an integer in 1-32.
* Output : a 32 bit mask.
* Prepares a 32 bit mask with required number of 1 bits on the MSB side.
*/
static
uint32_t
mask32bit
(
int
n
)
/*
read a big endian uint64_t at given address (potentially not 64-bits aligned)
* don't read more than 'available_bytes'
* (use 0 if no byte to read)
* (note: the compiler will optimize this, no need to do better)
*/
static
inline
uint64_t
U64
(
uint8_t
*
p
,
int
available_bytes
)
{
uint32_t
mask
=
0x0
;
if
(
n
%
32
==
0
)
return
0xffffffff
;
while
(
n
--
)
mask
=
(
mask
>>
1
)
^
0x80000000
;
uint64_t
a
=
0
;
uint64_t
b
=
0
;
uint64_t
c
=
0
;
uint64_t
d
=
0
;
uint64_t
e
=
0
;
uint64_t
f
=
0
;
uint64_t
g
=
0
;
uint64_t
h
=
0
;
switch
(
available_bytes
)
{
case
8
:
h
=
p
[
7
];
/* falltrough */
case
7
:
g
=
p
[
6
];
/* falltrough */
case
6
:
f
=
p
[
5
];
/* falltrough */
case
5
:
e
=
p
[
4
];
/* falltrough */
case
4
:
d
=
p
[
3
];
/* falltrough */
case
3
:
c
=
p
[
2
];
/* falltrough */
case
2
:
b
=
p
[
1
];
/* falltrough */
case
1
:
a
=
p
[
0
];
}
return
mask
;
return
(
a
<<
(
32
+
24
))
|
(
b
<<
(
32
+
16
))
|
(
c
<<
(
32
+
8
))
|
(
d
<<
32
)
|
(
e
<<
24
)
|
(
f
<<
16
)
|
(
g
<<
8
)
|
h
;
}
/*!
* @brief Create integrity cmac t for a given message.
* @param[in] stream_cipher Structure containing various variables to setup encoding
...
...
@@ -125,11 +136,8 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t o
uint64_t
c
;
uint64_t
M_D_2
;
int
rem_bits
;
uint32_t
mask
=
0
;
uint32_t
*
message
;
uint8_t
*
key
=
(
uint8_t
*
)
stream_cipher
->
context
;
message
=
(
uint32_t
*
)
stream_cipher
->
message
;
/* To operate 32 bit message internally. */
/* Load the Integrity Key for SNOW3G initialization as in section 4.4. */
memcpy
(
K
+
3
,
key
+
0
,
4
);
/*K[3] = key[0]; we assume
K[3]=key[0]||key[1]||...||key[31] , with key[0] the
...
...
@@ -181,11 +189,14 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t o
EVAL
=
0
;
c
=
0x1b
;
AssertFatal
(
stream_cipher
->
blength
%
8
==
0
,
"unsupported buffer length
\n
"
);
uint8_t
*
message
=
stream_cipher
->
message
;
/* for 0 <= i <= D-3 */
for
(
i
=
0
;
i
<
D
-
2
;
i
++
)
{
V
=
EVAL
^
(
(
uint64_t
)
hton_int32
(
message
[
2
*
i
])
<<
32
|
(
uint64_t
)
hton_int32
(
message
[
2
*
i
+
1
])
);
V
=
EVAL
^
U64
(
&
message
[
4
*
2
*
i
],
8
);
EVAL
=
MUL64
(
V
,
P
,
c
);
//printf ("Mi: %16X %16X\tEVAL: %16lX\n",hton_int32(message[2*i]),hton_int32(message[2*i+1]), EVAL);
}
/* for D-2 */
...
...
@@ -194,14 +205,7 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t o
if
(
rem_bits
==
0
)
rem_bits
=
64
;
mask
=
mask32bit
(
rem_bits
%
32
);
if
(
rem_bits
>
32
)
{
M_D_2
=
(
(
uint64_t
)
hton_int32
(
message
[
2
*
(
D
-
2
)])
<<
32
)
|
(
uint64_t
)
(
hton_int32
(
message
[
2
*
(
D
-
2
)
+
1
])
&
mask
);
}
else
{
M_D_2
=
(
(
uint64_t
)
hton_int32
(
message
[
2
*
(
D
-
2
)])
&
mask
)
<<
32
;
}
M_D_2
=
U64
(
&
message
[
4
*
(
2
*
(
D
-
2
))],
rem_bits
/
8
);
V
=
EVAL
^
M_D_2
;
EVAL
=
MUL64
(
V
,
P
,
c
);
...
...
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