Commit 2334f6f5 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/nas-issue-881' into integration_2025_w07 (!3176)

Refactor and extend NAS Registration Request

Extended NAS Registration Request generation and encoding according to
8.2.6 of 3GPP TS 24.501. Main topics:

- NAS Registration Type
- NAS KSI
- integrity protection
- NAS container encoding

Improvements:

- Add 5GMM Modes in NAS
- Introduced 5GMM state machine

Fixes:

- add 5GMM Capability IE to Registration Request
- closes #881, #819
parents bab13b80 bd429488
......@@ -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 {
......
......@@ -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;
} 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++;
*(buffer + encoded) = fgmmcapability->value;
}
// 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;
}
......@@ -30,6 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#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_ */
......@@ -30,11 +30,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#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));
}
......@@ -29,7 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#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);
......
......@@ -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(&registration_request->naskeysetidentifier, IEI_NULL) & 0x0f) << 4)
| (encode_5gs_registration_type(&registration_request->fgsregistrationtype) & 0x0f);
| (encode_5gs_registration_type(&registration_request->fgsregistrationtype, is_for) & 0x0f);
encoded++;
if ((encode_result = encode_5gs_mobile_identity(&registration_request->fgsmobileidentity, 0, buffer + encoded, len - encoded))
......@@ -86,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(&registration_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, &registration_request->fgmmcapability, len - encoded)) < 0)
return encode_result;
else
encoded += encode_result;
......
......@@ -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;
......
This diff is collapsed.
......@@ -51,6 +51,24 @@
/* 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;
/*
* 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];
......@@ -66,18 +84,24 @@ 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;
/* 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;
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;
/* Timer T3512 */
int t3512;
} 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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment