From 98d922e56883a985dce4ac2fa8f77c20265de9d5 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 20 May 2024 17:18:37 +0200 Subject: [PATCH 01/12] Introduced 5GMM state machine * according to 5.1.3.2.1 of 3GPP TS 24.501 --- openair3/NAS/NR_UE/nr_nas_msg.c | 8 ++++++++ openair3/NAS/NR_UE/nr_nas_msg.h | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index d7a1c42bf3..6166213fa9 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -505,6 +505,8 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); nas->registration_request_len = initialNasMsg->length; + /* set NAS 5GMM state */ + nas->fiveGMM_state = FGS_REGISTERED_INITIATED; } void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) @@ -812,6 +814,8 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, for (int i = 0; i < 4; i++) { initialNasMsg->nas_data[2 + i] = mac[i]; } + /* Set NAS 5GMM state */ + nas->fiveGMM_state = FGS_REGISTERED; } /** @@ -1004,6 +1008,8 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi for (int i = 0; i < 4; i++) { initialNasMsg->nas_data[2 + i] = mac[i]; } + /* Set NAS 5GMM state */ + nas->fiveGMM_state = FGS_DEREGISTERED_INITIATED; } static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, nas_pdu_session_req_t *pdu_req) @@ -1432,6 +1438,8 @@ void *nas_nrue(void *args_p) break; case FGS_DEREGISTRATION_ACCEPT_UE_ORIGINATING: LOG_I(NAS, "received deregistration accept\n"); + /* Set NAS 5GMM state */ + nas->fiveGMM_state = FGS_DEREGISTERED; break; case FGS_PDU_SESSION_ESTABLISHMENT_ACC: handle_pdu_session_accept(pdu_buffer, pdu_length); diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index b4a97a36d7..380da8cbbc 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -51,6 +51,14 @@ /* 3GPP TS 24.501: 9.11.3.50 Service type */ #define SERVICE_TYPE_DATA 0x1 +typedef enum fgs_mm_state_e { + FGS_DEREGISTERED, + FGS_DEREGISTERED_INITIATED, + FGS_REGISTERED_INITIATED, + FGS_REGISTERED, + FGS_SERVICE_REQUEST_INITIATED, +} fgs_mm_state_t; + /* Security Key for SA UE */ typedef struct { uint8_t kausf[32]; @@ -66,6 +74,8 @@ typedef struct { } ue_sa_security_key_t; typedef struct { + /* 5GS Mobility Management States (5.1.3.2.1 of 3GPP TS 24.501) */ + fgs_mm_state_t fiveGMM_state; uicc_t *uicc; ue_sa_security_key_t security; stream_security_container_t *security_container; From e3eb663085314199224fc69375e471f899262cf8 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 14 Aug 2024 11:19:49 +0200 Subject: [PATCH 02/12] Add 5GMM Modes in NAS * added fgs_mm_mode_t enum * added struct member to NAS * modes: FGS_IDLE, FGS_CONNECTED * according to 5GS mobility management (5GMM) modes 5.1.3.2.1.1 of TS 24.501 --- openair3/NAS/NR_UE/nr_nas_msg.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index 380da8cbbc..ae42174fda 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -59,6 +59,16 @@ typedef enum fgs_mm_state_e { FGS_SERVICE_REQUEST_INITIATED, } fgs_mm_state_t; +/* + * 5GS mobility management (5GMM) modes + * 5.1.3.2.1.1 of TS 24.501 + */ +typedef enum fgs_mm_mode_e { + FGS_NOT_CONNECTED, + FGS_IDLE, + FGS_CONNECTED, +} fgs_mm_mode_t; + /* Security Key for SA UE */ typedef struct { uint8_t kausf[32]; @@ -76,6 +86,8 @@ typedef struct { typedef struct { /* 5GS Mobility Management States (5.1.3.2.1 of 3GPP TS 24.501) */ fgs_mm_state_t fiveGMM_state; + /* 5GS Mobility Management mode */ + fgs_mm_mode_t fiveGMM_mode; uicc_t *uicc; ue_sa_security_key_t security; stream_security_container_t *security_container; From 54755b57aa4ed467cb271f75ea6723e149f66e34 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 27 Jun 2024 11:23:32 +0200 Subject: [PATCH 03/12] Add NAS Registration Request with type Mobility Registration Updating * ref TS 24.501 --- openair3/NAS/NR_UE/nr_nas_msg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 6166213fa9..57b3f1447b 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -469,7 +469,11 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) // Plain 5GMM msg registration_request_msg *mm_msg = &plain.mm_msg.registration_request; - mm_msg->fgsregistrationtype = INITIAL_REGISTRATION; + if (nas->fiveGMM_state == FGS_DEREGISTERED) { + mm_msg->fgsregistrationtype = INITIAL_REGISTRATION; + } else { + mm_msg->fgsregistrationtype = MOBILITY_REGISTRATION_UPDATING; + } mm_msg->naskeysetidentifier.naskeysetidentifier = 1; size += 1; if (nas->guti) { From 9dd1929ec07f92735a5bf542faacaebe2bc63418 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 24 Jan 2025 16:57:38 +0100 Subject: [PATCH 04/12] Add fgsnasmessagecontainer member to NAS Registration Request struct --- openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h index 686b0bc148..f820f3e03a 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h @@ -35,6 +35,7 @@ #include "NasKeySetIdentifier.h" #include "NrUESecurityCapability.h" #include "SecurityHeaderType.h" +#include "FGCNasMessageContainer.h" #ifndef REGISTRATION_REQUEST_H_ #define REGISTRATION_REQUEST_H_ @@ -102,6 +103,7 @@ typedef struct registration_request_msg_tag { NasKeySetIdentifier naskeysetidentifier; FGSMobileIdentity fgsmobileidentity; /* Optional fields */ + FGCNasMessageContainer fgsnasmessagecontainer; uint32_t presencemask; FGMMCapability fgmmcapability; NrUESecurityCapability nruesecuritycapability; From 4633eb88886593e654aa3afe1450b4b70dbc501c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 27 Nov 2024 14:44:00 +0100 Subject: [PATCH 05/12] Refactor 5GS registration type encoding (9.11.3.7 of 3GPP TS 24.501) --- .../NR_UE/5GS/5GMM/IES/FGSRegistrationType.c | 23 +++++++++++-------- .../NR_UE/5GS/5GMM/IES/FGSRegistrationType.h | 6 +++-- .../NR_UE/5GS/5GMM/MSG/RegistrationRequest.c | 3 ++- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.c index 81825f585a..68861c1142 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.c @@ -30,11 +30,14 @@ #include #include #include - +#include #include "TLVEncoder.h" #include "TLVDecoder.h" #include "FGSRegistrationType.h" +#define NO_FOLLOW_ON_REQUEST 0x0 +#define FOLLOW_ON_REQUEST 0x08 + int decode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype, uint8_t iei, uint8_t value, uint32_t len) { int decoded = 0; @@ -49,14 +52,14 @@ int decode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype, uint8 return decoded; } -int encode_5gs_registration_type(const FGSRegistrationType *fgsregistrationtype) +/** + * @brief Encode 5GS registration type (9.11.3.7 of 3GPP TS 24.501) + * Note: mandatory IE (IEI = 0) + */ +int encode_5gs_registration_type(const FGSRegistrationType *fgsregistrationtype, bool follow_on_request) { - uint8_t bufferReturn; - uint8_t *buffer = &bufferReturn; - uint8_t encoded = 0; - uint8_t iei = 0; - *(buffer + encoded) = 0x00 | (iei & 0xf0) | 0x8 | (*fgsregistrationtype & 0x7); - encoded++; - - return bufferReturn; + // Follow-on request bit + uint8_t foR = follow_on_request ? FOLLOW_ON_REQUEST : NO_FOLLOW_ON_REQUEST; + // Return encoded value + return (foR | (*fgsregistrationtype & 0x7)); } diff --git a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.h index ea42ac160e..7a0e832942 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.h @@ -29,7 +29,7 @@ #include #include #include - +#include #include "OctetString.h" #ifndef FGS_REGISTRATION_TYPE_H_ @@ -41,13 +41,15 @@ typedef uint8_t FGSRegistrationType; // clang-format off +/* 3GPP TS 24.501 Table 9.11.3.7.1: 5GS registration type IE */ #define INITIAL_REGISTRATION 0b001 #define MOBILITY_REGISTRATION_UPDATING 0b010 #define PERIODIC_REGISTRATION_UPDATING 0b011 #define EMERGENCY_REGISTRATION 0b100 +#define REG_TYPE_RESERVED 0b111 // clang-format on -int encode_5gs_registration_type(const FGSRegistrationType *fgsregistrationtype); +int encode_5gs_registration_type(const FGSRegistrationType *fgsregistrationtype, bool follow_on_request); int decode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype, uint8_t iei, uint8_t value, uint32_t len); diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c index 8f6fea900e..f71030f1f7 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c @@ -72,9 +72,10 @@ int encode_registration_request(const registration_request_msg *registration_req { int encoded = 0; int encode_result = 0; + bool is_for = true; // Follow-on request pending *(buffer + encoded) = ((encode_nas_key_set_identifier(®istration_request->naskeysetidentifier, IEI_NULL) & 0x0f) << 4) - | (encode_5gs_registration_type(®istration_request->fgsregistrationtype) & 0x0f); + | (encode_5gs_registration_type(®istration_request->fgsregistrationtype, is_for) & 0x0f); encoded++; if ((encode_result = encode_5gs_mobile_identity(®istration_request->fgsmobileidentity, 0, buffer + encoded, len - encoded)) From b9dc68b5ce345ea596d1abd6b598db35fd37a56d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 27 Nov 2024 14:46:49 +0100 Subject: [PATCH 06/12] Add RRC Inactive Indication and Timer T3512 to NAS struct definition --- openair3/NAS/NR_UE/nr_nas_msg.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index ae42174fda..6e33a5c523 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -96,6 +96,10 @@ typedef struct { uint8_t *registration_request_buf; uint32_t registration_request_len; instance_t UE_id; + /* RRC Inactive Indication */ + bool is_rrc_inactive; + /* Timer T3512 */ + int t3512; } nr_ue_nas_t; nr_ue_nas_t *get_ue_nas_info(module_id_t module_id); From 088939f5b099be8d0caa3f392194ca7f2346aba0 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 19 Dec 2024 10:49:39 +0100 Subject: [PATCH 07/12] Add set_fgs_registration_type to set 5GS Registration Type according to 3GPP TS 24.501 --- openair3/NAS/NR_UE/nr_nas_msg.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 57b3f1447b..3e5210644c 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -458,6 +458,33 @@ nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) return &nr_ue_nas[module_id]; } +static FGSRegistrationType set_fgs_registration_type(nr_ue_nas_t *nas) +{ + if (nas->fiveGMM_state == FGS_REGISTERED && nas->fiveGMM_mode == FGS_IDLE && nas->t3512) { + // TODO: if the timer expires, do PERIODIC_REGISTRATION_UPDATING + /** The UE shall initiate the registration procedure for + * mobility and periodic registration update according to + * 5.5.1.3.2 of 3GPP TS 24.501: Mobility and periodic + * registration update initiation */ + LOG_E(NAS, "Registration type periodic registration updating is not handled\n"); + return REG_TYPE_RESERVED; + } else if (nas->fiveGMM_state == FGS_REGISTERED) { + // in any other case, The UE in state 5GMM-REGISTERED shall indicate "mobility registration updating". + return MOBILITY_REGISTRATION_UPDATING; + } + + if (nas->fiveGMM_mode == FGS_CONNECTED && nas->is_rrc_inactive) { + /** the UE shall do the registration procedure for mobility + * and/or periodic registration update depending on the + * indication received from the lower layers according to + * 5.3.1.4 of 3GPP TS 24.501: 5GMM-CONNECTED mode with RRC inactive indication */ + LOG_E(NAS, "RRC inactive indication not handled by NAS\n"); + return REG_TYPE_RESERVED; + } + + return INITIAL_REGISTRATION; +} + void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) { int size = sizeof(fgmm_msg_header_t); From 0c8761aadd4767a51a281268459593872d0bcca0 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 19 Dec 2024 10:49:55 +0100 Subject: [PATCH 08/12] Refactor NAS 5GS Registration Request generation (3GPP TS 24.501) * send integrity protected Initial NAS Message when UE in 5GMM-IDLE mode has valid current 5G NAS security context: > According to 4.4.2.5 TS 24.501: > when a UE in 5GMM-IDLE mode establishes a new NAS signalling connection and has a valid current 5G NAS > security context, the UE shall transmit the initial NAS message integrity protected with the current 5G NAS security > context and further protect this message as specified in subclause 4.4.6. * set NAS key set identifier IE to "no key is available (UE to network)" * previously set to 1 which has no impact * set now to 111 in order to trigger new authentication * See 9.11.3.32 of 3GPP TS 24.501 * Do 5GS Registration Type "mobility registration updating" when 5GMM state is De-registered --- openair3/NAS/NR_UE/nr_nas_msg.c | 166 +++++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 44 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 3e5210644c..ba334d4290 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -458,6 +458,20 @@ nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) return &nr_ue_nas[module_id]; } +static FGSRegistrationType set_fgs_ksi(nr_ue_nas_t *nas) +{ + if (nas->fiveGMM_mode == FGS_IDLE) { + /** + * the UE is IDLE, therefore ngKSI was deleted, along all K_AMF, ciphering key, integrity key + * (i.e. the 5G NAS security context associated with the ngKSI is no longer valid) + * see 4.4.2 of 3GPP TS 24.501 + */ + return NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE; + } + return 0x0; +} + + static FGSRegistrationType set_fgs_registration_type(nr_ue_nas_t *nas) { if (nas->fiveGMM_state == FGS_REGISTERED && nas->fiveGMM_mode == FGS_IDLE && nas->t3512) { @@ -485,59 +499,126 @@ static FGSRegistrationType set_fgs_registration_type(nr_ue_nas_t *nas) return INITIAL_REGISTRATION; } +/** + * @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) { + LOG_I(NAS, "Generate Initial NAS Message: Registration Request\n"); int size = sizeof(fgmm_msg_header_t); - fgmm_nas_message_plain_t plain = {0}; + fgmm_nas_msg_security_protected_t sp = {0}; - // Plain 5GMM header - plain.header = set_mm_header(FGS_REGISTRATION_REQUEST, PLAIN_5GS_MSG); - size += sizeof(plain.header); - - // Plain 5GMM msg - registration_request_msg *mm_msg = &plain.mm_msg.registration_request; - if (nas->fiveGMM_state == FGS_DEREGISTERED) { - mm_msg->fgsregistrationtype = INITIAL_REGISTRATION; - } else { - mm_msg->fgsregistrationtype = MOBILITY_REGISTRATION_UPDATING; + /** Check whether the UE has a valid current 5G NAS security context + and set security protected 5GS NAS message header (see 9.1.1 of 3GPP TS 24.501) */ + bool has_security_context = nas->security_container && nas->security_container->integrity_context; + if (has_security_context) { + sp.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp.header.security_header_type = INTEGRITY_PROTECTED; + sp.header.sequence_number = nas->security.nas_count_ul & 0xff; + size += 7; } - mm_msg->naskeysetidentifier.naskeysetidentifier = 1; + + // Plain 5GMM message + sp.plain.header = set_mm_header(FGS_REGISTRATION_REQUEST, PLAIN_5GS_MSG); + size += sizeof(sp.plain.header); + registration_request_msg *rr = &sp.plain.mm_msg.registration_request; + + // 5GMM Registration Type + rr->fgsregistrationtype = set_fgs_registration_type(nas); size += 1; - if (nas->guti) { - size += fill_guti(&mm_msg->fgsmobileidentity, nas->guti); + if (rr->fgsregistrationtype == REG_TYPE_RESERVED) { + // currently only REG_TYPE_RESERVED is supported + LOG_E(NAS, "Initial NAS Message: Registration Request failed\n"); + return; + } + // NAS Key Set Identifier + rr->naskeysetidentifier.tsc = NAS_KEY_SET_IDENTIFIER_NATIVE; + rr->naskeysetidentifier.naskeysetidentifier = set_fgs_ksi(nas); + size += 1; + + // 5GMM Mobile Identity + if(nas->guti){ + size += fill_guti(&rr->fgsmobileidentity, nas->guti); + LOG_D(NAS, + "5G-GUTI in registration request: MCC: %u%u%u, MNC: %u%u, AMF Region ID: %u, AMF Set ID: %u, AMF Pointer: %u, 5G-TMSI: " + "%u\n", + nas->guti->mccdigit1, + nas->guti->mccdigit2, + nas->guti->mccdigit3, + nas->guti->mncdigit1, + nas->guti->mncdigit2, + nas->guti->amfregionid, + nas->guti->amfsetid, + nas->guti->amfpointer, + nas->guti->tmsi); } else { - size += fill_suci(&mm_msg->fgsmobileidentity, nas->uicc); + size += fill_suci(&rr->fgsmobileidentity, nas->uicc); + Suci5GSMobileIdentity_t *suci = &rr->fgsmobileidentity.suci; + LOG_D(NAS, + "SUCI in registration request: SUPI type: %d Type of Identity: %u MCC: %u%u%u, MNC: %u%u%u, \ + Routing Indicator %d%d%d%d Protection Scheme ID: %u, Home Network PKI: %u, Scheme Output: %s\n", + suci->supiformat, + suci->typeofidentity, + suci->mccdigit1, + suci->mccdigit2, + suci->mccdigit3, + suci->mncdigit1, + suci->mncdigit2, + nas->uicc->nmc_size == 2 ? 0 : suci->mncdigit3, + suci->routingindicatordigit1, + suci->routingindicatordigit2, + suci->routingindicatordigit3, + suci->routingindicatordigit4, + suci->protectionschemeId, + suci->homenetworkpki, + suci->schemeoutput); } -#if 0 - /* This cannot be sent in clear, the core network Open5GS rejects the UE. - * TODO: do we have to send this at some point? - * For the time being, let's keep it here for later proper fix. - */ - mm_msg->registration_request.presencemask |= REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT; - mm_msg->registration_request.fgmmcapability.iei = REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI; - mm_msg->registration_request.fgmmcapability.length = 1; - mm_msg->registration_request.fgmmcapability.value = 0x7; - size += 3; -#endif - - mm_msg->presencemask |= REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT; - mm_msg->nruesecuritycapability.iei = REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI; - mm_msg->nruesecuritycapability.length = 8; - mm_msg->nruesecuritycapability.fg_EA = 0xe0; - mm_msg->nruesecuritycapability.fg_IA = 0x60; - mm_msg->nruesecuritycapability.EEA = 0; - mm_msg->nruesecuritycapability.EIA = 0; + // Security Capability + rr->presencemask |= REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT; + rr->nruesecuritycapability.iei = REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI; + rr->nruesecuritycapability.length = 8; + rr->nruesecuritycapability.fg_EA = 0xe0; + rr->nruesecuritycapability.fg_IA = 0x60; + rr->nruesecuritycapability.EEA = 0; + rr->nruesecuritycapability.EIA = 0; size += 10; - // encode the message initialNasMsg->nas_data = malloc16_clear(size * sizeof(*initialNasMsg->nas_data)); + if (has_security_context) { + // security protected encoding + int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp.header, size); + initialNasMsg->length = + security_header_len + + mm_msg_encode(&sp.plain, initialNasMsg->nas_data + security_header_len, size - security_header_len); + /* integrity protection */ + nas_stream_cipher_t stream_cipher; + AssertFatal(nas->security.nas_count_ul <= 0xffffff, "fatal: NAS COUNT UL too big (todo: fix that)\n"); + uint8_t mac[4]; + stream_cipher.context = nas->security_container->integrity_context; + stream_cipher.count = nas->security.nas_count_ul++; + stream_cipher.bearer = 1; + stream_cipher.direction = 0; + // Security protected header is cleartext except the SN field + uint8_t cleartext_len = sizeof(sp.header) - 1; + // Message to be integrity protected + stream_cipher.message = initialNasMsg->nas_data + cleartext_len; + // Length of integrity protected message in bits + stream_cipher.blength = (initialNasMsg->length - cleartext_len) << 3; + stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, mac); + uint8_t mac_len = sizeof(sp.header.message_authentication_code); + uint8_t mac_start_octet = 2; + LOG_D(NAS, "Integrity protected initial NAS message: mac = %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); + for (int i = 0; i < mac_len; i++) { + initialNasMsg->nas_data[mac_start_octet + i] = mac[i]; + } + } else { + // plain encoding + initialNasMsg->length = mm_msg_encode(&sp.plain, initialNasMsg->nas_data, size); + LOG_D(NAS, "Plain Initial NAS Message: Registration Request\n"); + } nas->registration_request_buf = initialNasMsg->nas_data; - - initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); nas->registration_request_len = initialNasMsg->length; - /* set NAS 5GMM state */ - nas->fiveGMM_state = FGS_REGISTERED_INITIATED; } void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) @@ -563,6 +644,8 @@ void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) // 5G-S-TMSI size += fill_fgstmsi(&mm_msg->fiveg_s_tmsi, nas->guti); + /* message encoding */ + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); if (security_protected) { fgmm_nas_msg_security_protected_t sp = {0}; @@ -575,9 +658,6 @@ void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) // Payload: plain message sp.plain = plain; - // Allocate NAS message for encoding - initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); - // security protected encoding int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp.header, size); initialNasMsg->length = @@ -611,8 +691,6 @@ void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) initialNasMsg->nas_data[2 + i] = mac[i]; } else { // plain encoding - // Allocate NAS message for encoding - initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); LOG_I(NAS, "PLAIN_5GS_MSG initial NAS message: Service Request with length %d \n", initialNasMsg->length); } From 9447e4fb573bd2f8933630abd7442639dde0cc33 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 19 Dec 2024 10:32:41 +0100 Subject: [PATCH 09/12] Refactor 5GMM Capability encoding (9.11.3 of 3GPP TS 24.501) * add all relevant content fields according to the specs and do the encoding Related to #881 --- .../NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.c | 49 +++++++++++++++++-- .../NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.h | 24 ++++++++- .../NR_UE/5GS/5GMM/MSG/RegistrationRequest.c | 7 +-- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.c index c053070518..8e5c7d1364 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.c @@ -35,16 +35,55 @@ #include "TLVDecoder.h" #include "FGMMCapability.h" -int encode_5gmm_capability(const FGMMCapability *fgmmcapability, uint8_t iei, uint8_t *buffer, uint32_t len) +#define MIN_LENGTH_5GMM_CAPABILITY 3 + +/** + * @brief Encode 5GMM Capability IE (9.11.3 of 3GPP TS 24.501) + */ +int encode_5gmm_capability(uint8_t *buffer, const FGMMCapability *fgmmcapability, uint32_t len) { int encoded = 0; - if (iei) { + + // Ensure buffer length is sufficient + if (len < MIN_LENGTH_5GMM_CAPABILITY) { + printf("Buffer length insufficient for encoding 5GMM capability\n"); + return -1; + } + + if (fgmmcapability->iei) { *buffer = fgmmcapability->iei; encoded++; - *(buffer + encoded) = fgmmcapability->length; - encoded++; - *(buffer + encoded) = fgmmcapability->value; + } else { + printf("Missing IEI in fgmmcapability\n"); + } + + buffer[encoded] = fgmmcapability->length; + encoded++; + + // Encode octet 3 (mandatory) + buffer[encoded] = (fgmmcapability->sgc << 7) | (fgmmcapability->iphc_cp_cIoT << 6) | (fgmmcapability->n3_data << 5) + | (fgmmcapability->cp_cIoT << 4) | (fgmmcapability->restrict_ec << 3) | (fgmmcapability->lpp << 2) + | (fgmmcapability->ho_attach << 1) | fgmmcapability->s1_mode; + encoded++; + + // Encode octet 4 + if (fgmmcapability->length >= 2) { + buffer[encoded] = (fgmmcapability->racs << 7) | (fgmmcapability->nssaa << 6) | (fgmmcapability->lcs << 5) + | (fgmmcapability->v2x_cnpc5 << 4) | (fgmmcapability->v2x_cepc5 << 3) | (fgmmcapability->v2x << 2) + | (fgmmcapability->up_cIoT << 1) | fgmmcapability->srvcc; encoded++; } + + // Encode octet 5 + if (fgmmcapability->length >= 3) { + buffer[encoded] = (fgmmcapability->ehc_CP_ciot << 3) | (fgmmcapability->multiple_eUP << 2) | (fgmmcapability->wusa << 1) + | fgmmcapability->cag; + encoded++; + } + + // Encode octets 6 - 15 + if (fgmmcapability->length >= 4) + memset(&buffer[encoded], 0, fgmmcapability->length - 3); + return encoded; } diff --git a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.h index b125935f9d..fcbdded058 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.h @@ -30,6 +30,7 @@ #include #include #include +#include #include "OctetString.h" @@ -39,9 +40,28 @@ typedef struct { uint8_t iei; uint8_t length; - uint8_t value; + bool sgc; + bool iphc_cp_cIoT; + bool n3_data; + bool cp_cIoT; + bool restrict_ec; + bool lpp; + bool ho_attach; + bool s1_mode; + bool racs; + bool nssaa; + bool lcs; + bool v2x_cnpc5; + bool v2x_cepc5; + bool v2x; + bool up_cIoT; + bool srvcc; + bool ehc_CP_ciot; + bool multiple_eUP; + bool wusa; + bool cag; } FGMMCapability; -int encode_5gmm_capability(const FGMMCapability *fgmmcapability, uint8_t iei, uint8_t *buffer, uint32_t len); +int encode_5gmm_capability(uint8_t *buffer, const FGMMCapability *fgmmcapability, uint32_t len); #endif /* FGMM_CAPABILITY_H_ */ diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c index f71030f1f7..6b124a3b81 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c @@ -87,12 +87,7 @@ int encode_registration_request(const registration_request_msg *registration_req if ((registration_request->presencemask & REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT) == REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT) { - if ((encode_result = encode_5gmm_capability(®istration_request->fgmmcapability, - REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI, - buffer + encoded, - len - encoded)) - < 0) - // Return in case of error + if ((encode_result = encode_5gmm_capability(buffer + encoded, ®istration_request->fgmmcapability, len - encoded)) < 0) return encode_result; else encoded += encode_result; From 16b1b0e9cedb471c89deb70a56089cc558adc2b8 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 19 Dec 2024 10:29:27 +0100 Subject: [PATCH 10/12] Enable 5GMM Capability encoding in NAS Registration Request * this commit is enabling the handling of non-cleartext IEs in the NAS Registration Request message according to 24.501, 23.502 * send the full Registration Request message in the NAS Container of the SECURITY MODE COMPLETE * send the non-cleartext IEs in the NAS container of the Registration Request closes #881 --- openair3/NAS/NR_UE/nr_nas_msg.c | 81 ++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index ba334d4290..c49e7dafef 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -471,6 +471,43 @@ static FGSRegistrationType set_fgs_ksi(nr_ue_nas_t *nas) return 0x0; } +/** + * @brief Set contents of 5GMM capability + * @note Currently hardcoded, sending min length only (1 octet) + */ +static FGMMCapability set_fgmm_capability(nr_ue_nas_t *nas) +{ + FGMMCapability cap = {0}; + cap.iei = REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI; + cap.length = 1; + + cap.sgc = 0; + cap.iphc_cp_cIoT = 0; + cap.n3_data = 0; + cap.cp_cIoT = 0; + cap.restrict_ec = 0; + cap.lpp = 1; + cap.ho_attach = 1; + cap.s1_mode = 1; + + if (cap.length == 1) + return cap; // Send minimum length only, 1 octet + + cap.racs = 0; + cap.nssaa = 0; + cap.lcs = 0; + cap.v2x_cnpc5 = 0; + cap.v2x_cepc5 = 0; + cap.v2x = 0; + cap.up_cIoT = 0; + cap.srvcc = 0; + cap.ehc_CP_ciot = 0; + cap.multiple_eUP = 0; + cap.wusa = 0; + cap.cag = 0; + + return cap; +} static FGSRegistrationType set_fgs_registration_type(nr_ue_nas_t *nas) { @@ -583,10 +620,35 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) rr->nruesecuritycapability.EEA = 0; rr->nruesecuritycapability.EIA = 0; size += 10; - // encode the message - initialNasMsg->nas_data = malloc16_clear(size * sizeof(*initialNasMsg->nas_data)); + + // 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 */ + fgmm_nas_message_plain_t full_mm = sp.plain; + registration_request_msg *full_rr = &full_mm.mm_msg.registration_request; + int size_nct = size; + /* 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) { + 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) { - // security protected encoding + /* 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; + + // Security protected header encoding int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp.header, size); initialNasMsg->length = security_header_len @@ -612,13 +674,18 @@ 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 { - // plain encoding + /* 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"); } - nas->registration_request_buf = initialNasMsg->nas_data; - nas->registration_request_len = initialNasMsg->length; } void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) @@ -851,6 +918,8 @@ 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, From 81ec8d2e137145dc40df3ccc17a0c0b65c7f8a90 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 28 Jan 2025 18:31:11 +0100 Subject: [PATCH 11/12] 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); From bd429488148b5ff64f044c836045321504dd6e9e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 4 Feb 2025 16:07:55 +0100 Subject: [PATCH 12/12] Move debug log for SUCI and GUTI to the relvant processing functions --- openair3/NAS/NR_UE/nr_nas_msg.c | 61 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index dc11ce28c1..2be3e2cf8b 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -199,6 +199,24 @@ static int fill_suci(FGSMobileIdentity *mi, const uicc_t *uicc) mi->suci.mccdigit2 = uicc->imsiStr[1] - '0'; mi->suci.mccdigit3 = uicc->imsiStr[2] - '0'; memcpy(mi->suci.schemeoutput, uicc->imsiStr + 3 + uicc->nmc_size, strlen(uicc->imsiStr) - (3 + uicc->nmc_size)); + LOG_D(NAS, + "SUCI in registration request: SUPI type: %d Type of Identity: %u MCC: %u%u%u, MNC: %u%u%u, \ + Routing Indicator %d%d%d%d Protection Scheme ID: %u, Home Network PKI: %u, Scheme Output: %s\n", + mi->suci.supiformat, + mi->suci.typeofidentity, + mi->suci.mccdigit1, + mi->suci.mccdigit2, + mi->suci.mccdigit3, + mi->suci.mncdigit1, + mi->suci.mncdigit2, + uicc->nmc_size == 2 ? 0 : mi->suci.mncdigit3, + mi->suci.routingindicatordigit1, + mi->suci.routingindicatordigit2, + mi->suci.routingindicatordigit3, + mi->suci.routingindicatordigit4, + mi->suci.protectionschemeId, + mi->suci.homenetworkpki, + mi->suci.schemeoutput); return sizeof(Suci5GSMobileIdentity_t); } @@ -206,6 +224,18 @@ static int fill_guti(FGSMobileIdentity *mi, const Guti5GSMobileIdentity_t *guti) { AssertFatal(guti != NULL, "UE has no GUTI\n"); mi->guti = *guti; + LOG_D(NAS, + "5G-GUTI in registration request: MCC: %u%u%u, MNC: %u%u, AMF Region ID: %u, AMF Set ID: %u, AMF Pointer: %u, 5G-TMSI: " + "%u\n", + mi->guti.mccdigit1, + mi->guti.mccdigit2, + mi->guti.mccdigit3, + mi->guti.mncdigit1, + mi->guti.mncdigit2, + mi->guti.amfregionid, + mi->guti.amfsetid, + mi->guti.amfpointer, + mi->guti.tmsi); return 13; } @@ -576,39 +606,8 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas, // 5GMM Mobile Identity if(nas->guti){ size += fill_guti(&rr->fgsmobileidentity, nas->guti); - LOG_D(NAS, - "5G-GUTI in registration request: MCC: %u%u%u, MNC: %u%u, AMF Region ID: %u, AMF Set ID: %u, AMF Pointer: %u, 5G-TMSI: " - "%u\n", - nas->guti->mccdigit1, - nas->guti->mccdigit2, - nas->guti->mccdigit3, - nas->guti->mncdigit1, - nas->guti->mncdigit2, - nas->guti->amfregionid, - nas->guti->amfsetid, - nas->guti->amfpointer, - nas->guti->tmsi); } else { size += fill_suci(&rr->fgsmobileidentity, nas->uicc); - Suci5GSMobileIdentity_t *suci = &rr->fgsmobileidentity.suci; - LOG_D(NAS, - "SUCI in registration request: SUPI type: %d Type of Identity: %u MCC: %u%u%u, MNC: %u%u%u, \ - Routing Indicator %d%d%d%d Protection Scheme ID: %u, Home Network PKI: %u, Scheme Output: %s\n", - suci->supiformat, - suci->typeofidentity, - suci->mccdigit1, - suci->mccdigit2, - suci->mccdigit3, - suci->mncdigit1, - suci->mncdigit2, - nas->uicc->nmc_size == 2 ? 0 : suci->mncdigit3, - suci->routingindicatordigit1, - suci->routingindicatordigit2, - suci->routingindicatordigit3, - suci->routingindicatordigit4, - suci->protectionschemeId, - suci->homenetworkpki, - suci->schemeoutput); } // Security Capability