From 63d7f26cfd1d5992697b0c2b7244fb85830efd48 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 13 Nov 2024 10:03:27 +0100 Subject: [PATCH] Refactor NAS 5GMM messages structs definitions as per legacy code, the NAS functions in nr_nas_msg.c were encoding the header in the plain header contained in MM_msg (e.g. plain -> mm_msg -> header in fgs_nas_message_t). The same header was encoded in the mobility management message contained in the same struct (e.g. plain -> mm_msg -> registration_request -> protocoldiscriminator). As this was more complicated than necessary, the goal of this commit is to simplify the code and improve readability. Namely: * Refactor MM_msg into fgmm_nas_message_plain_t to contain (1) 5GMM Header (2) 5GMM Payload union * Use fgmm_nas_message_plain_t and fgmm_nas_msg_security_protected_t in the 5GMM NAS procedures * Remove NAS header IEs from 5GMM messages structs and use the header in fgs_nas_message_plain_t. This reduce also the repetitions of header members in each of the 5GMM messages structs. * Rename struct to distinguish between 5GMM and 5GSM * Remove fgs_nas_message_t and nas_msg_header_t, use directly basic 5GS struct definitions, simplify the code * The callbacks in nr_nas_msg.c are now doing (1) encode header with the common NAS lib (2) encode contents with the 5GMM libs * improve code readibility in the process --- .../5GS/5GMM/MSG/FGSAuthenticationResponse.h | 4 - .../FGSDeregistrationRequestUEOriginating.h | 4 - .../NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.h | 4 - .../5GS/5GMM/MSG/FGSNASSecurityModeComplete.h | 4 - .../5GS/5GMM/MSG/FGSUplinkNasTransport.h | 4 - .../NR_UE/5GS/5GMM/MSG/RegistrationAccept.h | 5 - .../NR_UE/5GS/5GMM/MSG/RegistrationRequest.h | 5 - openair3/NAS/NR_UE/5GS/NR_NAS_defs.h | 57 +-- openair3/NAS/NR_UE/5GS/fgs_nas_lib.c | 26 +- openair3/NAS/NR_UE/nr_nas_msg.c | 340 ++++++++---------- 10 files changed, 191 insertions(+), 262 deletions(-) diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.h index 6f5427531b..6c0f0eaa64 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.h @@ -50,10 +50,6 @@ typedef struct fgs_authentication_response_msg_tag { /* Mandatory fields */ - uint8_t protocoldiscriminator; - SecurityHeaderType securityheadertype: 4; - uint8_t sparehalfoctet: 4; - MessageType messagetype; AuthenticationResponseParameter authenticationresponseparameter; } fgs_authentication_response_msg; diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.h index 3c3bf3114f..6374b55895 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.h @@ -38,10 +38,6 @@ typedef struct fgs_deregistration_request_ue_originating_msg_tag { /* Mandatory fields */ - uint8_t protocoldiscriminator; - SecurityHeaderType securityheadertype: 4; - uint8_t sparehalfoctet: 4; - MessageType messagetype; FGSDeregistrationType deregistrationtype; NasKeySetIdentifier naskeysetidentifier; FGSMobileIdentity fgsmobileidentity; diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.h index 74cc6879a6..667cb80c59 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.h @@ -45,10 +45,6 @@ typedef struct fgmm_identity_response_msg_s { /* Mandatory fields */ - uint8_t protocoldiscriminator; - SecurityHeaderType securityheadertype: 4; - uint8_t sparehalfoctet: 4; - MessageType messagetype; FGSMobileIdentity fgsmobileidentity; } fgmm_identity_response_msg; diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.h index 01f6cc15d4..4c379dadee 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.h @@ -46,10 +46,6 @@ typedef struct fgs_security_mode_complete_msg_tag { /* Mandatory fields */ - uint8_t protocoldiscriminator; - SecurityHeaderType securityheadertype: 4; - uint8_t sparehalfoctet: 4; - MessageType messagetype; FGSMobileIdentity fgsmobileidentity; FGCNasMessageContainer fgsnasmessagecontainer; } fgs_security_mode_complete_msg; diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.h index 06ade93896..7b828a1ed3 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.h @@ -53,10 +53,6 @@ typedef struct FGSPayloadContainer_tag { typedef struct fgs_uplink_nas_transport_msg_tag { /* Mandatory fields */ - uint8_t protocoldiscriminator; - SecurityHeaderType securityheadertype: 4; - uint8_t sparehalfoctet: 4; - MessageType messagetype; PayloadContainerType payloadcontainertype; FGSPayloadContainer fgspayloadcontainer; /* Optional fields */ diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h index d48a8f21d4..91b024a7d8 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h @@ -49,12 +49,7 @@ typedef struct registration_accept_msg_tag { /* Mandatory fields */ - uint8_t protocoldiscriminator; - SecurityHeaderType securityheadertype: 4; - uint8_t sparehalfoctet: 4; - MessageType messagetype; FGSRegistrationResult fgsregistrationresult; - /* Optional fields */ FGSMobileIdentity *guti; } registration_accept_msg; diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h index 9112fa6795..686b0bc148 100644 --- a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h @@ -98,14 +98,9 @@ typedef enum registration_request_iei_tag { typedef struct registration_request_msg_tag { /* Mandatory fields */ - uint8_t protocoldiscriminator; - SecurityHeaderType securityheadertype: 4; - uint8_t sparehalfoctet: 4; - MessageType messagetype; FGSRegistrationType fgsregistrationtype; NasKeySetIdentifier naskeysetidentifier; FGSMobileIdentity fgsmobileidentity; - /* Optional fields */ uint32_t presencemask; FGMMCapability fgmmcapability; diff --git a/openair3/NAS/NR_UE/5GS/NR_NAS_defs.h b/openair3/NAS/NR_UE/5GS/NR_NAS_defs.h index 206cdab279..548909e2b3 100644 --- a/openair3/NAS/NR_UE/5GS/NR_NAS_defs.h +++ b/openair3/NAS/NR_UE/5GS/NR_NAS_defs.h @@ -258,45 +258,26 @@ typedef struct { uint8_t message_type; } fgmm_msg_header_t; -/// 5GS legacy defs - -typedef union { +/* Plain 5GMM NAS message (5GS) */ +typedef struct { fgmm_msg_header_t header; - registration_request_msg registration_request; - fgs_service_request_msg_t service_request; - fgmm_identity_response_msg fgs_identity_response; - fgs_authentication_response_msg fgs_auth_response; - fgs_deregistration_request_ue_originating_msg fgs_deregistration_request_ue_originating; - fgs_security_mode_complete_msg fgs_security_mode_complete; - registration_complete_msg registration_complete; - fgs_uplink_nas_transport_msg uplink_nas_transport; -} MM_msg; - -typedef struct { - MM_msg mm_msg; /* 5GS Mobility Management messages */ -} fgs_nas_message_plain_t; - -typedef struct { - fgs_nas_message_security_header_t header; - fgs_nas_message_plain_t plain; -} fgs_nas_message_security_protected_t; -typedef union { - fgs_nas_message_security_header_t header; - fgs_nas_message_security_protected_t security_protected; - fgs_nas_message_plain_t plain; -} fgs_nas_message_t; -typedef struct { union { - fgmm_msg_header_t plain_nas_msg_header; - struct security_protected_nas_msg_header_s { - uint8_t ex_protocol_discriminator; - uint8_t security_header_type; - uint16_t message_authentication_code1; - uint16_t message_authentication_code2; - uint8_t sequence_number; - } security_protected_nas_msg_header_t; - } choice; -} nas_msg_header_t; + registration_request_msg registration_request; + fgs_service_request_msg_t service_request; + fgmm_identity_response_msg fgs_identity_response; + fgs_authentication_response_msg fgs_auth_response; + fgs_deregistration_request_ue_originating_msg fgs_deregistration_request_ue_originating; + fgs_security_mode_complete_msg fgs_security_mode_complete; + registration_complete_msg registration_complete; + fgs_uplink_nas_transport_msg uplink_nas_transport; + } mm_msg; /* 5GS Mobility Management messages */ +} fgmm_nas_message_plain_t; + +/* Security protected 5GMM NAS message (5GS) */ +typedef struct { + fgs_nas_message_security_header_t header; + fgmm_nas_message_plain_t plain; +} fgmm_nas_msg_security_protected_t; /// 5GSM - 5GS session management @@ -317,7 +298,7 @@ typedef struct { /// Function prototypes -int mm_msg_encode(const MM_msg *mm_msg, uint8_t *buffer, uint32_t len); +int mm_msg_encode(const fgmm_nas_message_plain_t *mm_msg, uint8_t *buffer, uint32_t len); int nas_protected_security_header_encode(uint8_t *buffer, const fgs_nas_message_security_header_t *header, int length); int _nas_mm_msg_encode_header(const fgmm_msg_header_t *header, uint8_t *buffer, uint32_t len); diff --git a/openair3/NAS/NR_UE/5GS/fgs_nas_lib.c b/openair3/NAS/NR_UE/5GS/fgs_nas_lib.c index 75f045846d..b077476b31 100644 --- a/openair3/NAS/NR_UE/5GS/fgs_nas_lib.c +++ b/openair3/NAS/NR_UE/5GS/fgs_nas_lib.c @@ -48,15 +48,15 @@ int _nas_mm_msg_encode_header(const fgmm_msg_header_t *header, uint8_t *buffer, return (size); } -int mm_msg_encode(const MM_msg *mm_msg, uint8_t *buffer, uint32_t len) +int mm_msg_encode(const fgmm_nas_message_plain_t *p, uint8_t *buffer, uint32_t len) { LOG_FUNC_IN; int header_result; int encode_result; - uint8_t msg_type = mm_msg->header.message_type; + uint8_t msg_type = p->header.message_type; - /* First encode the EMM message header */ - header_result = _nas_mm_msg_encode_header(&mm_msg->header, buffer, len); + /* First encode the 5GMM message header */ + header_result = _nas_mm_msg_encode_header(&p->header, buffer, len); if (header_result < 0) { LOG_TRACE(ERROR, @@ -71,29 +71,29 @@ int mm_msg_encode(const MM_msg *mm_msg, uint8_t *buffer, uint32_t len) switch (msg_type) { case FGS_REGISTRATION_REQUEST: - encode_result = encode_registration_request(&mm_msg->registration_request, buffer, len); + encode_result = encode_registration_request(&p->mm_msg.registration_request, buffer, len); break; case FGS_IDENTITY_RESPONSE: - encode_result = encode_fgmm_identity_response(buffer, &mm_msg->fgs_identity_response, len); + encode_result = encode_fgmm_identity_response(buffer, &p->mm_msg.fgs_identity_response, len); break; case FGS_AUTHENTICATION_RESPONSE: - encode_result = encode_fgs_authentication_response(&mm_msg->fgs_auth_response, buffer, len); + encode_result = encode_fgs_authentication_response(&p->mm_msg.fgs_auth_response, buffer, len); break; case FGS_SECURITY_MODE_COMPLETE: - encode_result = encode_fgs_security_mode_complete(&mm_msg->fgs_security_mode_complete, buffer, len); + encode_result = encode_fgs_security_mode_complete(&p->mm_msg.fgs_security_mode_complete, buffer, len); break; case FGS_UPLINK_NAS_TRANSPORT: - encode_result = encode_fgs_uplink_nas_transport(&mm_msg->uplink_nas_transport, buffer, len); + encode_result = encode_fgs_uplink_nas_transport(&p->mm_msg.uplink_nas_transport, buffer, len); break; case FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING: encode_result = - encode_fgs_deregistration_request_ue_originating(&mm_msg->fgs_deregistration_request_ue_originating, buffer, len); + encode_fgs_deregistration_request_ue_originating(&p->mm_msg.fgs_deregistration_request_ue_originating, buffer, len); break; case FGS_SERVICE_REQUEST: - encode_result = encode_fgs_service_request(buffer, &mm_msg->service_request, len); + encode_result = encode_fgs_service_request(buffer, &p->mm_msg.service_request, len); break; default: - LOG_TRACE(ERROR, " Unexpected message type: 0x%x", mm_msg->header.message_type); + LOG_TRACE(ERROR, " Unexpected message type: 0x%x", p->header.message_type); encode_result = TLV_ENCODE_WRONG_MESSAGE_TYPE; break; /* TODO: Handle not standard layer 3 messages: SERVICE_REQUEST */ @@ -103,7 +103,7 @@ int mm_msg_encode(const MM_msg *mm_msg, uint8_t *buffer, uint32_t len) LOG_TRACE(ERROR, " Failed to encode L3 EMM message 0x%x " "(%d)", - mm_msg->header.message_type, + p->header.message_type, encode_result); } diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 6109f69234..bd848e9c55 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -47,6 +47,7 @@ #include "PduSessionEstablishmentAccept.h" #include "RegistrationAccept.h" #include "SORTransparentContainer.h" +#include "FGSIdentityResponse.h" #include "T.h" #include "aka_functions.h" #include "assertions.h" @@ -428,29 +429,24 @@ 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) { int size = sizeof(fgmm_msg_header_t); - fgs_nas_message_t nas_msg = {0}; - MM_msg *mm_msg; + fgmm_nas_message_plain_t plain = {0}; - mm_msg = &nas_msg.plain.mm_msg; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_REGISTRATION_REQUEST; + // Plain 5GMM header + fgmm_msg_header_t *mm_header = &plain.header; + mm_header->ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header->security_header_type = PLAIN_5GS_MSG; + mm_header->message_type = FGS_REGISTRATION_REQUEST; + size += 3; - // set registration request - mm_msg->registration_request.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - size += 1; - mm_msg->registration_request.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->registration_request.messagetype = FGS_REGISTRATION_REQUEST; - size += 1; - mm_msg->registration_request.fgsregistrationtype = INITIAL_REGISTRATION; - mm_msg->registration_request.naskeysetidentifier.naskeysetidentifier = 1; + // Plain 5GMM msg + registration_request_msg *mm_msg = &plain.mm_msg.registration_request; + mm_msg->fgsregistrationtype = INITIAL_REGISTRATION; + mm_msg->naskeysetidentifier.naskeysetidentifier = 1; size += 1; if (nas->guti) { - size += fill_guti(&mm_msg->registration_request.fgsmobileidentity, nas->guti); + size += fill_guti(&mm_msg->fgsmobileidentity, nas->guti); } else { - size += fill_suci(&mm_msg->registration_request.fgsmobileidentity, nas->uicc); + size += fill_suci(&mm_msg->fgsmobileidentity, nas->uicc); } #if 0 @@ -465,20 +461,20 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) size += 3; #endif - 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 = 0xe0; - mm_msg->registration_request.nruesecuritycapability.fg_IA = 0x60; - mm_msg->registration_request.nruesecuritycapability.EEA = 0; - mm_msg->registration_request.nruesecuritycapability.EIA = 0; + 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; size += 10; // encode the message initialNasMsg->nas_data = malloc16_clear(size * sizeof(*initialNasMsg->nas_data)); nas->registration_request_buf = initialNasMsg->nas_data; - initialNasMsg->length = mm_msg_encode(mm_msg, initialNasMsg->nas_data, size); + initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); nas->registration_request_len = initialNasMsg->length; } @@ -486,47 +482,52 @@ void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) { LOG_I(NAS, "Generate initial NAS message: Service Request\n"); int size = 0; - fgs_nas_message_t nas_msg = {0}; - memset(&nas_msg, 0, sizeof(nas_msg)); + // NAS is security protected if has valid security contexts bool security_protected = nas->security_container->ciphering_context && nas->security_container->integrity_context; - MM_msg *mm_msg; + fgmm_nas_message_plain_t plain = {0}; + fgs_service_request_msg_t *mm_msg; + fgmm_nas_msg_security_protected_t sp = {0}; + fgmm_msg_header_t *mm_header; if (security_protected) { /* Set security protected 5GS NAS message header (see 9.1.1 of 3GPP TS 24.501) */ - nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - nas_msg.header.security_header_type = INTEGRITY_PROTECTED; - nas_msg.header.sequence_number = nas->security.nas_count_ul & 0xff; + 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 += sizeof(fgs_nas_message_security_header_t); - mm_msg = &nas_msg.security_protected.plain.mm_msg; + mm_msg = &sp.plain.mm_msg.service_request; + // Plain 5GMM header + mm_header = &sp.plain.header; } else { // Set Mobility Management plain message header - mm_msg = &nas_msg.plain.mm_msg; + mm_msg = &plain.mm_msg.service_request; + // Plain 5GMM header + mm_header = &plain.header; } - // Fill MM plain message header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_SERVICE_REQUEST; - size += sizeof(mm_msg->header); + mm_header->ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header->security_header_type = PLAIN_5GS_MSG; + mm_header->message_type = FGS_SERVICE_REQUEST; + size += sizeof(*mm_header); // Fill Service Request // Service Type - mm_msg->service_request.serviceType = SERVICE_TYPE_DATA; + mm_msg->serviceType = SERVICE_TYPE_DATA; // NAS key set identifier - mm_msg->service_request.naskeysetidentifier.naskeysetidentifier = NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE; - mm_msg->service_request.naskeysetidentifier.tsc = NAS_KEY_SET_IDENTIFIER_NATIVE; + mm_msg->naskeysetidentifier.naskeysetidentifier = NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE; + mm_msg->naskeysetidentifier.tsc = NAS_KEY_SET_IDENTIFIER_NATIVE; size += 1; // 5G-S-TMSI - size += fill_fgstmsi(&mm_msg->service_request.fiveg_s_tmsi, nas->guti); + 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) { // security protected encoding - int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->nas_data), &(nas_msg.header), size); + int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp.header, size); initialNasMsg->length = security_header_len - + mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); + + mm_msg_encode(&sp.plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; nas_stream_cipher_t stream_cipher; @@ -555,7 +556,7 @@ void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) initialNasMsg->nas_data[2 + i] = mac[i]; } else { // plain encoding - initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data), size); + initialNasMsg->length = mm_msg_encode(&plain, (uint8_t *)(initialNasMsg->nas_data), size); LOG_I(NAS, "PLAIN_5GS_MSG initial NAS message: Service Request with length %d \n", initialNasMsg->length); } } @@ -563,31 +564,25 @@ void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype, uicc_t *uicc) { int size = sizeof(fgmm_msg_header_t); - fgs_nas_message_t nas_msg; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); - MM_msg *mm_msg; + fgmm_nas_message_plain_t plain = {0}; - mm_msg = &nas_msg.plain.mm_msg; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_IDENTITY_RESPONSE; + // Plain 5GMM header + fgmm_msg_header_t *mm_header = &plain.header; + mm_header->ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header->security_header_type = PLAIN_5GS_MSG; + mm_header->message_type = FGS_IDENTITY_RESPONSE; + size += 3; // set identity response - mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - size += 1; - mm_msg->fgs_identity_response.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->fgs_identity_response.messagetype = FGS_IDENTITY_RESPONSE; - size += 1; + fgmm_identity_response_msg *mm_msg = &plain.mm_msg.fgs_identity_response; if (identitytype == FGS_MOBILE_IDENTITY_SUCI) { - size += fill_suci(&mm_msg->fgs_identity_response.fgsmobileidentity, uicc); + size += fill_suci(&mm_msg->fgsmobileidentity, uicc); } // encode the message initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); - initialNasMsg->length = mm_msg_encode(mm_msg, initialNasMsg->nas_data, size); + initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); } static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, uint8_t *buf) @@ -599,31 +594,23 @@ static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialN memcpy(res.value, nas->security.res, 16); int size = sizeof(fgmm_msg_header_t); - fgs_nas_message_t nas_msg; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); - MM_msg *mm_msg; + fgmm_nas_message_plain_t plain = {0}; - mm_msg = &nas_msg.plain.mm_msg; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_AUTHENTICATION_RESPONSE; - - // set authentication response - mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - size += 1; - mm_msg->fgs_identity_response.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->fgs_identity_response.messagetype = FGS_AUTHENTICATION_RESPONSE; - size += 1; + // Plain 5GMM header + fgmm_msg_header_t *mm_header = &plain.header; + mm_header->ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header->security_header_type = PLAIN_5GS_MSG; + mm_header->message_type = FGS_AUTHENTICATION_RESPONSE; + size += 3; // set response parameter - mm_msg->fgs_auth_response.authenticationresponseparameter.res = res; + fgs_authentication_response_msg *mm_msg = &plain.mm_msg.fgs_auth_response; + mm_msg->authenticationresponseparameter.res = res; size += 18; // encode the message initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); - initialNasMsg->length = mm_msg_encode(mm_msg, initialNasMsg->nas_data, size); + initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); // Free res value after encode free(res.value); } @@ -639,37 +626,32 @@ int nas_itti_kgnb_refresh_req(instance_t instance, const uint8_t kgnb[32]) static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg) { int size = sizeof(fgmm_msg_header_t); - fgs_nas_message_t nas_msg; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); - - MM_msg *mm_msg; + fgmm_nas_msg_security_protected_t nas_msg = {0}; nas_stream_cipher_t stream_cipher; uint8_t mac[4]; // 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; + fgs_nas_message_security_header_t *sp = &nas_msg.header; + sp->protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp->security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; + sp->sequence_number = nas->security.nas_count_ul & 0xff; size += 7; - mm_msg = &nas_msg.security_protected.plain.mm_msg; + // Plain 5GMM Security Mode Complete msg + fgmm_nas_message_plain_t *plain = &nas_msg.plain; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_SECURITY_MODE_COMPLETE; + // Plain 5GMM header + fgmm_msg_header_t *mm_header = &plain->header; + mm_header->ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header->security_header_type = PLAIN_5GS_MSG; + mm_header->message_type = FGS_SECURITY_MODE_COMPLETE; + size += 3; - // set security mode complete - mm_msg->fgs_security_mode_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - size += 1; - mm_msg->fgs_security_mode_complete.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->fgs_security_mode_complete.messagetype = FGS_SECURITY_MODE_COMPLETE; - size += 1; + // Plain 5GMM payload + fgs_security_mode_complete_msg *mm_msg = &plain->mm_msg.fgs_security_mode_complete; + size += fill_imeisv(&mm_msg->fgsmobileidentity, nas->uicc); - size += fill_imeisv(&mm_msg->fgs_security_mode_complete.fgsmobileidentity, nas->uicc); - - mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.value = nas->registration_request_buf; - mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.length = nas->registration_request_len; + mm_msg->fgsnasmessagecontainer.nasmessagecontainercontents.value = nas->registration_request_buf; + mm_msg->fgsnasmessagecontainer.nasmessagecontainercontents.length = nas->registration_request_len; size += (nas->registration_request_len + 2); // encode the message @@ -679,7 +661,7 @@ 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->nas_data + security_header_len), size - security_header_len); + + mm_msg_encode(plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; @@ -774,29 +756,26 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, SORTransparentContainer *sortransparentcontainer) { int length = 0; - fgs_nas_message_t nas_msg; nas_stream_cipher_t stream_cipher; uint8_t mac[4]; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); - fgs_nas_message_security_protected_t *sp_msg; + fgmm_nas_msg_security_protected_t sp = {0}; - sp_msg = &nas_msg.security_protected; // set security protected header - 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 = nas->security.nas_count_ul & 0xff; + sp.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp.header.message_authentication_code = 0; + sp.header.sequence_number = nas->security.nas_count_ul & 0xff; length = 7; // set plain 5GMM header - sp_msg->plain.mm_msg.header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - length += 1; - sp_msg->plain.mm_msg.header.security_header_type = PLAIN_5GS_MSG; - length += 1; - sp_msg->plain.mm_msg.header.message_type = FGS_REGISTRATION_COMPLETE; - length += 1; + fgmm_msg_header_t *mm_header = &sp.plain.header; + mm_header->ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header->security_header_type = PLAIN_5GS_MSG; + mm_header->message_type = FGS_REGISTRATION_COMPLETE; + length += 3; + registration_complete_msg *mm_msg = &sp.plain.mm_msg.registration_complete; if (sortransparentcontainer) { - sp_msg->plain.mm_msg.registration_complete.sortransparentcontainer = sortransparentcontainer; + mm_msg->sortransparentcontainer = sortransparentcontainer; length += sortransparentcontainer->sortransparentcontainercontents.length; } @@ -804,19 +783,19 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, initialNasMsg->nas_data = malloc_or_fail(length * sizeof(*initialNasMsg->nas_data)); initialNasMsg->length = length; // encode security protected header - int encoded = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp_msg->header, length); + int encoded = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp.header, length); if (encoded < 0) { LOG_E(NAS, "generateRegistrationComplete: failed to encode security protected header\n"); return; } // encode 5GMM plain header - encoded = _nas_mm_msg_encode_header(&sp_msg->plain.mm_msg.header, initialNasMsg->nas_data + encoded, length - encoded); + encoded = _nas_mm_msg_encode_header(mm_header, initialNasMsg->nas_data + encoded, length - encoded); if (encoded < 0) { LOG_E(NAS, "generateRegistrationComplete: failed to encode 5GMM plain header\n"); return; } - encode_registration_complete(&sp_msg->plain.mm_msg.registration_complete, initialNasMsg->nas_data + encoded, length - encoded); + encode_registration_complete(mm_msg, initialNasMsg->nas_data + encoded, length - encoded); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; @@ -863,36 +842,37 @@ static void handleDownlinkNASTransport(uint8_t *pdu_buffer, uint32_t msg_length) static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, const nas_deregistration_req_t *req) { - fgs_nas_message_t nas_msg = {0}; - fgs_nas_message_security_protected_t *sp_msg; - sp_msg = &nas_msg.security_protected; - 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 = nas->security.nas_count_ul & 0xff; - int size = sizeof(sp_msg->header); + fgmm_nas_msg_security_protected_t sp_msg = {0}; + fgs_nas_message_security_header_t *sp_header = &sp_msg.header; + sp_header->protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp_header->security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp_header->message_authentication_code = 0; + sp_header->sequence_number = nas->security.nas_count_ul & 0xff; + int size = sizeof(sp_msg.header); - fgs_deregistration_request_ue_originating_msg *dereg_req = &sp_msg->plain.mm_msg.fgs_deregistration_request_ue_originating; - dereg_req->protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + // Plain 5GMM header + fgmm_msg_header_t *mm_header = &sp_msg.plain.header; + mm_header->ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header->security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; + mm_header->message_type = FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING; + size += 3; + + // Plain 5GMM + fgs_deregistration_request_ue_originating_msg *mm_msg = &sp_msg.plain.mm_msg.fgs_deregistration_request_ue_originating; + mm_msg->deregistrationtype.switchoff = NORMAL_DEREGISTRATION; + mm_msg->deregistrationtype.reregistration_required = REREGISTRATION_NOT_REQUIRED; + mm_msg->deregistrationtype.access_type = TGPP_ACCESS; + mm_msg->naskeysetidentifier.naskeysetidentifier = 1; size += 1; - dereg_req->securityheadertype = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; - size += 1; - dereg_req->messagetype = FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING; - size += 1; - dereg_req->deregistrationtype.switchoff = NORMAL_DEREGISTRATION; - dereg_req->deregistrationtype.reregistration_required = REREGISTRATION_NOT_REQUIRED; - dereg_req->deregistrationtype.access_type = TGPP_ACCESS; - dereg_req->naskeysetidentifier.naskeysetidentifier = 1; - size += 1; - size += fill_guti(&dereg_req->fgsmobileidentity, nas->guti); + size += fill_guti(&mm_msg->fgsmobileidentity, nas->guti); // encode the message initialNasMsg->nas_data = calloc_or_fail(size, sizeof(*initialNasMsg->nas_data)); - int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, &nas_msg.header, size); + int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, sp_header, size); initialNasMsg->length = security_header_len - + mm_msg_encode(&sp_msg->plain.mm_msg, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); + + mm_msg_encode(&sp_msg.plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); nas_stream_cipher_t stream_cipher; @@ -929,7 +909,6 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, nas_pdu_session_req_t *pdu_req) { int size = 0; - fgs_nas_message_t nas_msg = {0}; // setup pdu session establishment request uint16_t req_length = 7; @@ -943,69 +922,68 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * pdu_session_establish.pdusessiontype = pdu_req->pdusession_type; encode_pdu_session_establishment_request(&pdu_session_establish, req_buffer); - MM_msg *mm_msg; nas_stream_cipher_t stream_cipher; 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 = nas->security.nas_count_ul & 0xff; + + // 5GMM security protected message + fgmm_nas_msg_security_protected_t sp_msg = {0}; + // 5GMM security protected message header + fgs_nas_message_security_header_t *sp_header = &sp_msg.header; + sp_header->protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp_header->security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp_header->sequence_number = nas->security.nas_count_ul & 0xff; size += 7; - mm_msg = &nas_msg.security_protected.plain.mm_msg; + fgmm_nas_message_plain_t *plain = &sp_msg.plain; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_UPLINK_NAS_TRANSPORT; + // Plain 5GMM header + fgmm_msg_header_t *mm_header = &plain->header; + mm_header->ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header->security_header_type = PLAIN_5GS_MSG; + mm_header->message_type = FGS_UPLINK_NAS_TRANSPORT; + size += 3; - // set uplink nas transport - mm_msg->uplink_nas_transport.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + fgs_uplink_nas_transport_msg *mm_msg = &plain->mm_msg.uplink_nas_transport; + mm_msg->payloadcontainertype.iei = 0; + mm_msg->payloadcontainertype.type = 1; size += 1; - mm_msg->uplink_nas_transport.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->uplink_nas_transport.messagetype = FGS_UPLINK_NAS_TRANSPORT; - size += 1; - - mm_msg->uplink_nas_transport.payloadcontainertype.iei = 0; - mm_msg->uplink_nas_transport.payloadcontainertype.type = 1; - size += 1; - mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.length = req_length; - mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.value = req_buffer; + mm_msg->fgspayloadcontainer.payloadcontainercontents.length = req_length; + mm_msg->fgspayloadcontainer.payloadcontainercontents.value = req_buffer; size += (2 + req_length); - mm_msg->uplink_nas_transport.pdusessionid = pdu_req->pdusession_id; - mm_msg->uplink_nas_transport.requesttype = 1; + mm_msg->pdusessionid = pdu_req->pdusession_id; + mm_msg->requesttype = 1; size += 3; const bool has_nssai_sd = pdu_req->sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 const size_t nssai_len = has_nssai_sd ? 4 : 1; - mm_msg->uplink_nas_transport.snssai.length = nssai_len; + mm_msg->snssai.length = nssai_len; // Fixme: it seems there are a lot of memory errors in this: this value was on the stack, // but pushed in a itti message to another thread // this kind of error seems in many places in 5G NAS - mm_msg->uplink_nas_transport.snssai.value = calloc(1, nssai_len); - mm_msg->uplink_nas_transport.snssai.value[0] = pdu_req->sst; + mm_msg->snssai.value = calloc(1, nssai_len); + mm_msg->snssai.value[0] = pdu_req->sst; if (has_nssai_sd) - INT24_TO_BUFFER(pdu_req->sd, &mm_msg->uplink_nas_transport.snssai.value[1]); + INT24_TO_BUFFER(pdu_req->sd, &mm_msg->snssai.value[1]); size += 1 + 1 + nssai_len; int dnnSize = strlen(nas->uicc->dnnStr); - mm_msg->uplink_nas_transport.dnn.value = calloc(1, dnnSize + 1); - mm_msg->uplink_nas_transport.dnn.length = dnnSize + 1; - mm_msg->uplink_nas_transport.dnn.value[0] = dnnSize; - memcpy(mm_msg->uplink_nas_transport.dnn.value + 1, nas->uicc->dnnStr, dnnSize); + mm_msg->dnn.value = calloc(1, dnnSize + 1); + mm_msg->dnn.length = dnnSize + 1; + mm_msg->dnn.value[0] = dnnSize; + memcpy(mm_msg->dnn.value + 1, nas->uicc->dnnStr, dnnSize); size += (1 + 1 + dnnSize + 1); // encode the message initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); - int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, &nas_msg.header, size); + int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, sp_header, size); initialNasMsg->length = security_header_len - + mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); + + mm_msg_encode(plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); // Free allocated memory after encode free(req_buffer); - free(mm_msg->uplink_nas_transport.dnn.value); - free(mm_msg->uplink_nas_transport.snssai.value); + free(mm_msg->dnn.value); + free(mm_msg->snssai.value); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; @@ -1153,7 +1131,7 @@ static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_b return; const uint8_t *end = pdu_buffer + pdu_length; - if (((nas_msg_header_t *)(pdu_buffer))->choice.security_protected_nas_msg_header_t.security_header_type > 0) { + if (((fgs_nas_message_security_header_t *)(pdu_buffer))->security_header_type > 0) { pdu_buffer += SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH; }