Merge remote-tracking branch 'origin/bugfix-nas-security-msg-type' into integration_2025_w27 (!3494)
bugfix: read msg_type only after deciphering
There was a problem with accessing msg_type from the input buffer before
deciphering, giving obviously wrong value.
CI team: we should add a test in the CI with NAS ciphering + integrity
(connection to the core) set to not null (I suggest nea2/nia2). With
openair's core, this is done by setting this in the amf config file
(nia1 and nea2 at the top of the list):
supported_integrity_algorithms:
- "NIA2"
- "NIA1"
- "NIA0"
supported_encryption_algorithms:
- "NEA2"
- "NEA1"
- "NEA0"
And also put full security in the AS. This is done with this in the gnb
config file:
security = {
ciphering_algorithms = ( "nea2", "nea0" );
integrity_algorithms = ( "nia2", "nia1", "nia0" );
drb_ciphering = "yes";
drb_integrity = "yes"
};
Ideally we should test this with both openair UE and cots UE. But as a
strict minimum do for openair UE (this is where the bug was).
No need to do much traffic, a few ping is enough. But if you want to
check throughput with full security, why not.
This commit is contained in:
@@ -65,9 +65,9 @@ oc-cn5g:
|
||||
Host: avra
|
||||
NetworkScript: echo "inet 172.21.6.102"
|
||||
RunIperf3Server: False
|
||||
Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ci-ran"
|
||||
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ci-ran"
|
||||
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jan oaicicd-core-for-ci-ran %%log_dir%%"
|
||||
Deploy: "! scripts/oc-cn5g-deploy.sh /opt/oai-cn5g-fed-develop-2025-jun oaicicd-core-for-ci-ran"
|
||||
Undeploy: "! scripts/oc-cn5g-undeploy.sh /opt/oai-cn5g-fed-develop-2025-jun oaicicd-core-for-ci-ran"
|
||||
LogCollect: "! scripts/oc-cn5g-logcollect.sh /opt/oai-cn5g-fed-develop-2025-jun oaicicd-core-for-ci-ran %%log_dir%%"
|
||||
|
||||
oc-cn5g-20897:
|
||||
Host: cacofonix
|
||||
@@ -89,8 +89,8 @@ matix-cn5g:
|
||||
Host: matix
|
||||
NetworkScript: docker exec prod-trf-gen ip a show dev eth0
|
||||
RunIperf3Server: False
|
||||
Deploy: "cd /opt/oai-cn5g-fed-v2/docker-compose && python3 ./core-network.py --type start-basic"
|
||||
Undeploy: "cd /opt/oai-cn5g-fed-v2/docker-compose && python3 ./core-network.py --type stop-basic"
|
||||
Deploy: "cd /opt/oai-cn5g-fed-v2-jun-2025/docker-compose && python3 ./core-network.py --type start-basic"
|
||||
Undeploy: "cd /opt/oai-cn5g-fed-v2-jun-2025/docker-compose && python3 ./core-network.py --type stop-basic"
|
||||
LogCollect:
|
||||
- "docker logs oai-smf > %%log_dir%%/oai-smf.log"
|
||||
- "docker logs oai-amf > %%log_dir%%/oai-amf.log"
|
||||
|
||||
@@ -213,7 +213,7 @@ security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
ciphering_algorithms = ( "nea2", "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
@@ -223,7 +223,7 @@ security = {
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
drb_integrity = "yes";
|
||||
};
|
||||
|
||||
log_config :
|
||||
|
||||
@@ -212,7 +212,7 @@ security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
ciphering_algorithms = ( "nea2", "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
@@ -222,7 +222,7 @@ security = {
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
drb_integrity = "yes";
|
||||
};
|
||||
|
||||
log_config :
|
||||
|
||||
@@ -301,7 +301,44 @@ static void nas_security_decrypt_payload(nr_ue_nas_t *nas, byte_array_t buffer,
|
||||
free(decrypted);
|
||||
}
|
||||
|
||||
static security_state_t nas_security_rx_process(nr_ue_nas_t *nas, byte_array_t buffer, fgs_nas_msg_t msg_type)
|
||||
static fgs_nas_msg_t get_msg_type(uint8_t *pdu_buffer, uint32_t length)
|
||||
{
|
||||
if (pdu_buffer == NULL)
|
||||
goto error;
|
||||
|
||||
/* get security header type */
|
||||
if (length < 2)
|
||||
goto error;
|
||||
|
||||
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 security_state_t nas_security_rx_process(nr_ue_nas_t *nas, byte_array_t buffer)
|
||||
{
|
||||
if (nas->security_container == NULL)
|
||||
return NAS_SECURITY_NO_SECURITY_CONTEXT;
|
||||
@@ -314,9 +351,11 @@ static security_state_t nas_security_rx_process(nr_ue_nas_t *nas, byte_array_t b
|
||||
LOG_D(NAS, "Security type is: %s\n", print_info(security_type, security_header_type_s, sizeofArray(security_header_type_s)));
|
||||
|
||||
switch (security_type) {
|
||||
case PLAIN_5GS_MSG:
|
||||
case PLAIN_5GS_MSG: {
|
||||
fgs_nas_msg_t msg_type = get_msg_type(buffer.buf, buffer.len);
|
||||
return unprotected_allowed(buffer, msg_type) ? NAS_SECURITY_UNPROTECTED : NAS_SECURITY_BAD_INPUT;
|
||||
break;
|
||||
}
|
||||
case INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX:
|
||||
stream_security_container_delete(nas->security_container);
|
||||
nas->security_container = NULL;
|
||||
@@ -1707,43 +1746,6 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
|
||||
}
|
||||
}
|
||||
|
||||
static fgs_nas_msg_t get_msg_type(uint8_t *pdu_buffer, uint32_t length)
|
||||
{
|
||||
if (pdu_buffer == NULL)
|
||||
goto error;
|
||||
|
||||
/* get security header type */
|
||||
if (length < 2)
|
||||
goto error;
|
||||
|
||||
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(nr_ue_nas_t *nas, const as_nas_info_t *initial_nas_msg)
|
||||
{
|
||||
MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_UPLINK_DATA_REQ);
|
||||
@@ -2003,13 +2005,13 @@ void *nas_nrue(void *args_p)
|
||||
NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length);
|
||||
|
||||
byte_array_t ba = {.buf = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.nas_data, .len = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length};
|
||||
fgs_nas_msg_t msg_type = get_msg_type(ba.buf, ba.len);
|
||||
security_state_t security_state = nas_security_rx_process(nas, ba, msg_type);
|
||||
security_state_t security_state = nas_security_rx_process(nas, ba);
|
||||
if (security_state > NAS_SECURITY_INTEGRITY_PASSED) {
|
||||
LOG_E(NAS, "NAS integrity failed, discard incoming message: security state is %s\n", security_state_info[security_state].text);
|
||||
break;
|
||||
}
|
||||
|
||||
fgs_nas_msg_t msg_type = get_msg_type(ba.buf, ba.len);
|
||||
if (msg_type == FGS_REGISTRATION_ACCEPT) {
|
||||
handle_registration_accept(nas, ba.buf, ba.len);
|
||||
} else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) {
|
||||
@@ -2071,13 +2073,13 @@ void *nas_nrue(void *args_p)
|
||||
uint8_t *pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.nas_data;
|
||||
int pdu_length = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length;
|
||||
byte_array_t buffer = {.buf = pdu_buffer, .len = pdu_length};
|
||||
fgs_nas_msg_t msg_type = get_msg_type(pdu_buffer, pdu_length);
|
||||
security_state_t security_state = nas_security_rx_process(nas, buffer, msg_type);
|
||||
security_state_t security_state = nas_security_rx_process(nas, buffer);
|
||||
if (security_state > NAS_SECURITY_INTEGRITY_PASSED) {
|
||||
LOG_E(NAS, "NAS integrity failed, discard incoming message\n");
|
||||
break;
|
||||
}
|
||||
|
||||
fgs_nas_msg_t msg_type = get_msg_type(pdu_buffer, pdu_length);
|
||||
LOG_I(NAS,
|
||||
"[UE %ld] Received %s type %s with length %u\n",
|
||||
nas->UE_id,
|
||||
|
||||
Reference in New Issue
Block a user