From 81ec8d2e137145dc40df3ccc17a0c0b65c7f8a90 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 28 Jan 2025 18:31:11 +0100 Subject: [PATCH] Rework protection of initial NAS signaling messages (REGISTRATION REQUEST) as per 3GPP TS 33.501 * Without a valid 5G NAS security context: * Send REGISTRATION REQUEST with cleartext IEs only. * After activating a security context via Security Mode Control: wrap the entire REGISTRATION REQUEST (with both non-cleartext and cleartext) in a NAS message container IE, include it in SECURITY MODE COMPLETE * With a valid 5G NAS security context: * If non-cleartext IEs are needed, wrap the entire message in a NAS message container IE and cipher it. * If only cleartext IEs are needed, send the message directly without the NAS message container IE. --- openair2/RRC/NR_UE/rrc_UE.c | 3 +- openair3/NAS/NR_UE/nr_nas_msg.c | 76 +++++++++++++++++++-------------- openair3/NAS/NR_UE/nr_nas_msg.h | 4 +- 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 26b9f51046..3fbe3663f0 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1106,7 +1106,8 @@ static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const if (IS_SA_MODE(get_softmodem_params())) { as_nas_info_t initialNasMsg; nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id); - generateRegistrationRequest(&initialNasMsg, nas); + // Send Initial NAS message (Registration Request) before Security Mode control procedure + generateRegistrationRequest(&initialNasMsg, nas, false); nas_msg = (char *)initialNasMsg.nas_data; nas_msg_length = initialNasMsg.length; } else { diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index c49e7dafef..dc11ce28c1 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -539,10 +539,10 @@ static FGSRegistrationType set_fgs_registration_type(nr_ue_nas_t *nas) /** * @brief Generate 5GS Registration Request (8.2.6 of 3GPP TS 24.501) */ -void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) +void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas, bool is_security_mode) { LOG_I(NAS, "Generate Initial NAS Message: Registration Request\n"); - int size = sizeof(fgmm_msg_header_t); + int size = sizeof(fgmm_msg_header_t); // cleartext size fgmm_nas_msg_security_protected_t sp = {0}; /** Check whether the UE has a valid current 5G NAS security context @@ -621,32 +621,50 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) rr->nruesecuritycapability.EIA = 0; size += 10; - // Allocate memory for Initial NAS message - initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); - - /* Handle non-cleartext IEs - create a copy of the cleartext 5GMM message and add non-cleartext IEs */ + /* Create a copy of the cleartext 5GMM message, add non-cleartext IEs if necessary */ fgmm_nas_message_plain_t full_mm = sp.plain; registration_request_msg *full_rr = &full_mm.mm_msg.registration_request; - int size_nct = size; + int size_nct = size; // non-cleartext size + bool cleartext_only = true; /* 5GMM Capability (non-cleartext IE) - 24.501 8.2.6.3 The UE shall include this IE, unless the UE performs a periodic registration updating procedure. */ if (full_rr->fgsregistrationtype != PERIODIC_REGISTRATION_UPDATING) { + cleartext_only = false; // The UE needs to send non-cleartext IE full_rr->presencemask |= REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT; full_rr->fgmmcapability = set_fgmm_capability(nas); FGMMCapability *cap = &full_rr->fgmmcapability; size_nct += sizeof(cap->length) + sizeof(cap->iei) + cap->length; } - if (has_security_context) { - /* The UE includes the entire 5GMM NAS Registration Request (with both cleartext and non-cleartext IEs) - in the NAS message container IE. The value of the NAS message container IE is then ciphered. - The UE sends a 5GMM NAS Registration Request message containing cleartext IEs and the NAS message container IE. */ - OctetString *nasmessagecontainercontents = &rr->fgsnasmessagecontainer.nasmessagecontainercontents; - nasmessagecontainercontents->value = calloc_or_fail(size_nct, sizeof(*nasmessagecontainercontents->value)); - nasmessagecontainercontents->length = mm_msg_encode(&full_mm, nasmessagecontainercontents->value, size_nct); - size += (nasmessagecontainercontents->length + 2); - rr->presencemask |= REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT; + if (is_security_mode) { + /* Encode both cleartext IEs and non-cleartext IEs Registration Request message in Security Mode Complete. + The UE includes the full Registration Request in the NAS container IE + and sends it within the Security Mode Complete message. (24.501 4.4.6, 23.502 4.2.2.2.2) */ + LOG_D(NAS, "Full Initial NAS Message: Registration Request in the NAS container of Security Mode Complete\n"); + initialNasMsg->nas_data = malloc_or_fail(size_nct * sizeof(*initialNasMsg->nas_data)); + initialNasMsg->length = mm_msg_encode(&full_mm, initialNasMsg->nas_data, size_nct); + } else if (!has_security_context) { + /* If no valid 5G NAS security context exists, the UE sends a plain Registration Request including cleartext IEs only. */ + LOG_D(NAS, "Plain Initial NAS Message: Registration Request\n"); + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); + initialNasMsg->length = mm_msg_encode(&sp.plain, initialNasMsg->nas_data, size); + } else { + /* If the UE has a valid current 5G NAS security context, then it includes the entire 5GMM NAS Registration Request + (with both cleartext and non-cleartext IEs) in the NAS message container IE. The value of the NAS message container IE is + then ciphered. The UE sends a 5GMM NAS Registration Request message containing cleartext IEs along with the NAS message + container IE. */ + LOG_D(NAS, "Initial NAS Message: Registration Request with ciphered NAS container\n"); + + // NAS message container + if (!cleartext_only) { + OctetString *nasmessagecontainercontents = &rr->fgsnasmessagecontainer.nasmessagecontainercontents; + nasmessagecontainercontents->value = calloc_or_fail(size_nct, sizeof(*nasmessagecontainercontents->value)); + nasmessagecontainercontents->length = mm_msg_encode(&full_mm, nasmessagecontainercontents->value, size_nct); + size += (nasmessagecontainercontents->length + 2); + rr->presencemask |= REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT; + } + // Allocate buffer (including NAS message container size) + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); // Security protected header encoding int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp.header, size); @@ -674,17 +692,6 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) for (int i = 0; i < mac_len; i++) { initialNasMsg->nas_data[mac_start_octet + i] = mac[i]; } - - } else { - /* If no valid 5G NAS security context exists, the UE sends a cleartext Registration Request. - For non-cleartext IEs, the UE includes the full Registration Request in the NAS container IE - and sends it within the Security Mode Complete message. (24.501 4.4.6, 23.502 4.2.2.2.2) */ - // Encode cleartext Registration Request message in Security Mode Complete - nas->registration_request_buf = malloc_or_fail(size_nct * sizeof(*nas->registration_request_buf)); - nas->registration_request_len = mm_msg_encode(&full_mm, nas->registration_request_buf, size_nct); - // Plain NAS Registration Request encoding - initialNasMsg->length = mm_msg_encode(&sp.plain, initialNasMsg->nas_data, size); - LOG_D(NAS, "Plain Initial NAS Message: Registration Request\n"); } } @@ -843,9 +850,14 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia fgs_security_mode_complete_msg *mm_msg = &plain->mm_msg.fgs_security_mode_complete; size += fill_imeisv(&mm_msg->fgsmobileidentity, nas->uicc); - mm_msg->fgsnasmessagecontainer.nasmessagecontainercontents.value = nas->registration_request_buf; - mm_msg->fgsnasmessagecontainer.nasmessagecontainercontents.length = nas->registration_request_len; - size += (nas->registration_request_len + 2); + /* After activating a 5G NAS security context resulting from a security mode control send the full + NAS Registration Request in the message container IE of the SECURITY MODE COMPLETE message (24.501 4.4.6) */ + as_nas_info_t rr; + generateRegistrationRequest(&rr, nas, true); + FGCNasMessageContainer *container = &mm_msg->fgsnasmessagecontainer; + container->nasmessagecontainercontents.value = rr.nas_data; + container->nasmessagecontainercontents.length = rr.length; + size += (rr.length + 2); // encode the message initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); @@ -918,8 +930,6 @@ static void handle_security_mode_command(nr_ue_nas_t *nas, as_nas_info_t *initia nas_itti_kgnb_refresh_req(nas->UE_id, nas->security.kgnb); generateSecurityModeComplete(nas, initialNasMsg); - // free Registration Request message after encoding - free(nas->registration_request_buf); } static void generateRegistrationComplete(nr_ue_nas_t *nas, diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index 6e33a5c523..c46ba6fcd4 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -93,8 +93,6 @@ typedef struct { stream_security_container_t *security_container; Guti5GSMobileIdentity_t *guti; bool termination_procedure; - uint8_t *registration_request_buf; - uint32_t registration_request_len; instance_t UE_id; /* RRC Inactive Indication */ bool is_rrc_inactive; @@ -103,7 +101,7 @@ typedef struct { } nr_ue_nas_t; nr_ue_nas_t *get_ue_nas_info(module_id_t module_id); -void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas); +void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas, bool is_security_mode); void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas); void *nas_nrue_task(void *args_p); void *nas_nrue(void *args_p);