From 4736f970551dd3483469bb7a9dba6345e880dd7c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 14 Aug 2024 11:24:45 +0200 Subject: [PATCH 1/7] Indicate to NAS that the RRC connection has been established with a Connection Establishment Indication * ITTI from RRC to NAS * according to 5.3.1.3 of 3GPP TS 24.501 * set 5GMM mode to CONNECTED --- openair2/COMMON/rrc_messages_def.h | 1 + openair2/COMMON/rrc_messages_types.h | 1 + openair2/RRC/NR_UE/rrc_UE.c | 4 ++++ openair3/NAS/NR_UE/nr_nas_msg.c | 10 ++++++++++ 4 files changed, 16 insertions(+) diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index cb4805ff5e..55f1708cc2 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -74,6 +74,7 @@ MESSAGE_DEF(NAS_CELL_SELECTION_IND, MESSAGE_PRIORITY_MED, cell_info_ind_t, nas_c MESSAGE_DEF(NAS_PAGING_IND, MESSAGE_PRIORITY_MED, paging_ind_t, nas_paging_ind) MESSAGE_DEF(NAS_CONN_ESTABLI_CNF, MESSAGE_PRIORITY_MED, nas_establish_cnf_t, nas_conn_establi_cnf) MESSAGE_DEF(NAS_CONN_RELEASE_IND, MESSAGE_PRIORITY_MED, nas_release_ind_t, nas_conn_release_ind) +MESSAGE_DEF(NR_NAS_CONN_ESTABLISH_IND, MESSAGE_PRIORITY_MED, nas_establish_ind_t, nr_nas_conn_establish_ind) MESSAGE_DEF(NR_NAS_CONN_RELEASE_IND, MESSAGE_PRIORITY_MED, NRNasConnReleaseInd, nr_nas_conn_release_ind) MESSAGE_DEF(NAS_UPLINK_DATA_CNF, MESSAGE_PRIORITY_MED, ul_info_transfer_cnf_t, nas_ul_data_cnf) MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, dl_info_transfer_ind_t, nas_dl_data_ind) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 5dc1e27f93..c7974a2746 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -84,6 +84,7 @@ #define NAS_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_paging_ind #define NAS_CONN_ESTABLI_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_establi_cnf #define NAS_CONN_RELEASE_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_release_ind +#define NR_NAS_CONN_ESTABLISH_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_nas_conn_establish_ind #define NR_NAS_CONN_RELEASE_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_nas_conn_release_ind #define NAS_UPLINK_DATA_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_ul_data_cnf #define NAS_DOWNLINK_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_dl_data_ind diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 85adc82328..261ff2a60c 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1182,6 +1182,10 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, // enter RRC_CONNECTED rrc->nrRrcState = RRC_STATE_CONNECTED_NR; + // Indicate to NAS that the RRC connection has been established (5.3.1.3 of 3GPP TS 24.501) + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_NAS_CONN_ESTABLISH_IND); + itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, msg_p); + // set the content of RRCSetupComplete message // TODO procedues described in 5.3.3.4 seems more complex than what we actualy do rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier); diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 3c8da56280..803a4d6b55 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1516,6 +1516,16 @@ void *nas_nrue(void *args_p) break; } + case NR_NAS_CONN_ESTABLISH_IND: { + nas->fiveGMM_mode = FGS_CONNECTED; + LOG_I(NAS, + "[UE %ld] Received %s: asCause %u\n", + nas->UE_id, + ITTI_MSG_NAME(msg_p), + NR_NAS_CONN_ESTABLISH_IND(msg_p).asCause); + break; + } + case NAS_CONN_ESTABLI_CNF: { LOG_I(NAS, "[UE %ld] Received %s: errCode %u, length %u\n", From ca869d8fd3001104fa8ea635428ea1b2691264f8 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Feb 2025 07:44:35 +0100 Subject: [PATCH 2/7] Pass to RRC the 5G-S-TMSI extracted from NAS Registration Accept * NAS -> RRC: RRC receives an ITTI message with NAS 5GMM indication message containing the 5G-S-TMSI derived from NAS GUTI * 5G-S-TMSI is stored in the RRC instance and to be later encoded in the RRCSetup --- openair2/COMMON/as_message.h | 8 ++++++++ openair2/COMMON/rrc_messages_def.h | 1 + openair2/COMMON/rrc_messages_types.h | 1 + openair2/RRC/NR_UE/rrc_UE.c | 8 ++++++++ openair2/RRC/NR_UE/rrc_defs.h | 3 +++ openair3/NAS/NR_UE/nr_nas_msg.c | 14 ++++++++++++++ 6 files changed, 35 insertions(+) diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h index 5a29d6881b..31d53d12fe 100644 --- a/openair2/COMMON/as_message.h +++ b/openair2/COMMON/as_message.h @@ -404,6 +404,13 @@ typedef struct nas_detach_req_s { bool wait_release; } nas_detach_req_t; +/** + * @brief 5GS mobility management information + * @ref clause 9.11.3 of 3GPP TS 24.501 + */ +typedef struct nas_5gmm_ind_s { + uint64_t fiveG_STMSI; +} nas_5gmm_ind_t; /* * -------------------------------------------------------------------------- * NAS information transfer @@ -578,6 +585,7 @@ typedef struct as_message_s { rab_establish_cnf_t rab_establish_cnf; rab_release_req_t rab_release_req; rab_release_ind_t rab_release_ind; + nas_5gmm_ind_t Nas5GMMInd; } __attribute__((__packed__)) msg; } as_message_t; diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 55f1708cc2..841c44d612 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -63,6 +63,7 @@ MESSAGE_DEF(NAS_CONN_ESTABLI_REQ, MESSAGE_PRIORITY_MED, nas_establish_req_t, nas MESSAGE_DEF(NAS_UPLINK_DATA_REQ, MESSAGE_PRIORITY_MED, ul_info_transfer_req_t, nas_ul_data_req) MESSAGE_DEF(NAS_DETACH_REQ, MESSAGE_PRIORITY_MED, nas_detach_req_t, nas_detach_req) MESSAGE_DEF(NAS_DEREGISTRATION_REQ, MESSAGE_PRIORITY_MED, nas_deregistration_req_t, nas_deregistration_req) +MESSAGE_DEF(NAS_5GMM_IND, MESSAGE_PRIORITY_MED, nas_5gmm_ind_t, nas_5gmm_ind) MESSAGE_DEF(NAS_RAB_ESTABLI_RSP, MESSAGE_PRIORITY_MED, rab_establish_rsp_t, nas_rab_est_rsp) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index c7974a2746..2446bbe4b3 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -76,6 +76,7 @@ #define NAS_UPLINK_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_ul_data_req #define NAS_DETACH_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_detach_req #define NAS_DEREGISTRATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_deregistration_req +#define NAS_5GMM_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_5gmm_ind #define NAS_RAB_ESTABLI_RSP(mSGpTR) (mSGpTR)->ittiMsg.nas_rab_est_rsp diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 261ff2a60c..313347ed43 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -601,6 +601,8 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx) rrc->as_security_activated = false; rrc->detach_after_release = false; rrc->reconfig_after_reestab = false; + /* 5G-S-TMSI */ + rrc->fiveG_S_TMSI = UINT64_MAX; FILE *f = NULL; if (uecap_file) @@ -2098,6 +2100,12 @@ void *rrc_nrue(void *notUsed) break; } + case NAS_5GMM_IND: { + nas_5gmm_ind_t *req = &NAS_5GMM_IND(msg_p); + rrc->fiveG_S_TMSI = req->fiveG_STMSI; + break; + } + default: LOG_E(NR_RRC, "[UE %ld] Received unexpected message %s\n", rrc->ue_id, ITTI_MSG_NAME(msg_p)); break; diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 29c03afd5f..ee46a343d7 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -239,6 +239,9 @@ typedef struct NR_UE_RRC_INST_s { Rrc_State_NR_t nrRrcState; // flag to identify 1st reconfiguration after reestablishment bool reconfig_after_reestab; + // 5G-S-TMSI + uint64_t fiveG_S_TMSI; + //Sidelink params NR_SL_PreconfigurationNR_r16_t *sl_preconfig; // NTN params diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 803a4d6b55..d259ea0dba 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -77,6 +77,8 @@ static nr_ue_nas_t nr_ue_nas[MAX_NAS_UE] = {0}; TYPE_DEF(NAS_SECURITY_INTEGRITY_PASSED, 4) \ TYPE_DEF(NAS_SECURITY_BAD_INPUT, 5) +const char *nr_release_cause_desc[] = {"RRC_CONNECTION_FAILURE", "RRC_RESUME_FAILURE", "OTHER"}; + typedef enum { FOREACH_STATE(TO_ENUM) } security_state_t; static const text_info_t security_state_info[] = {FOREACH_STATE(TO_TEXT)}; @@ -1365,6 +1367,15 @@ static void send_nas_detach_req(nr_ue_nas_t *nas, bool wait_release) itti_send_msg_to_task(TASK_RRC_NRUE, nas->UE_id, msg); } +static void send_nas_5gmm_ind(instance_t instance, const Guti5GSMobileIdentity_t *guti) +{ + MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_5GMM_IND); + nas_5gmm_ind_t *ind = &NAS_5GMM_IND(msg); + LOG_I(NR_RRC, "5G-GUTI: AMF pointer %u, AMF Set ID %u, 5G-TMSI %u \n", guti->amfpointer, guti->amfsetid, guti->tmsi); + ind->fiveG_STMSI = ((uint64_t)guti->amfsetid << 38) | ((uint64_t)guti->amfpointer << 32) | guti->tmsi; + itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); +} + static void request_default_pdusession(nr_ue_nas_t *nas) { MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ); @@ -1439,6 +1450,9 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff LOG_W(NAS, "no GUTI in registration accept\n"); } + if(nas->guti) + send_nas_5gmm_ind(nas->UE_id, nas->guti); + as_nas_info_t initialNasMsg = {0}; generateRegistrationComplete(nas, &initialNasMsg, NULL); if (initialNasMsg.length > 0) { From fb318e8e3fa8ca1b8cb08edbaef6a847c38cf255 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Feb 2025 07:45:24 +0100 Subject: [PATCH 3/7] Cleanup commented out code in nas_nrue --- openair3/NAS/NR_UE/nr_nas_msg.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index d259ea0dba..8a51111cf3 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1495,11 +1495,6 @@ void *nas_nrue(void *args_p) NAS_CELL_SELECTION_CNF(msg_p).errCode, NAS_CELL_SELECTION_CNF(msg_p).cellID, NAS_CELL_SELECTION_CNF(msg_p).tac); - // as_stmsi_t s_tmsi={0, 0}; - // as_nas_info_t nas_info; - // plmn_t plmnID={0, 0, 0, 0}; - // generateRegistrationRequest(&nas_info); - // nr_nas_itti_nas_establish_req(0, AS_TYPE_ORIGINATING_SIGNAL, s_tmsi, plmnID, nas_info.data, nas_info.length, 0); break; case NAS_CELL_SELECTION_IND: From 36a39b25a13dda3ee70525d59e9d882c5121bdc9 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Feb 2025 07:46:04 +0100 Subject: [PATCH 4/7] Set 5GMM Mode to IDLE when receiving NR_NAS_CONN_RELEASE_IND > In N1 mode, upon indication from lower layers that the access stratum connection has been released, the UE shall enter 5GMM-IDLE mode and consider the N1 NAS signalling connection released (3GPP TS 24.501) --- openair3/NAS/NR_UE/nr_nas_msg.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 8a51111cf3..f78caf39f9 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1565,8 +1565,12 @@ void *nas_nrue(void *args_p) break; } - case NR_NAS_CONN_RELEASE_IND: - LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", nas->UE_id, ITTI_MSG_NAME(msg_p), NR_NAS_CONN_RELEASE_IND(msg_p).cause); + case NR_NAS_CONN_RELEASE_IND: { + LOG_I(NAS, "[UE %ld] Received %s: cause %s\n", + nas->UE_id, ITTI_MSG_NAME (msg_p), nr_release_cause_desc[NR_NAS_CONN_RELEASE_IND (msg_p).cause]); + /* In N1 mode, upon indication from lower layers that the access stratum connection has been released, + the UE shall enter 5GMM-IDLE mode and consider the N1 NAS signalling connection released (3GPP TS 24.501) */ + nas->fiveGMM_mode = FGS_IDLE; // TODO handle connection release if (nas->termination_procedure) { /* the following is not clean, but probably necessary: we need to give @@ -1577,7 +1581,7 @@ void *nas_nrue(void *args_p) itti_wait_tasks_unblock(); /* will unblock ITTI to stop nr-uesoftmodem */ } break; - + } case NAS_UPLINK_DATA_CNF: LOG_I(NAS, "[UE %ld] Received %s: UEid %u, errCode %u\n", From c6cc00633f155cc6506465b3b13a84cf37022372 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 7 Feb 2025 07:47:07 +0100 Subject: [PATCH 5/7] Rework handling of initial NAS message in RRCSetupComplete generation * use initialNasMsg to store nas messages buffer and length * buffer is dynamically allocated in generateRegistrationRequest, so do the same in NSA and free dynamic allocated data afterwards --- openair2/RRC/NR_UE/rrc_UE.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 313347ed43..9575fa1940 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1125,26 +1125,34 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const uint8_t Transaction_id) { uint8_t buffer[100]; - const char *nas_msg; - int nas_msg_length; + as_nas_info_t initialNasMsg; if (IS_SA_MODE(get_softmodem_params())) { - as_nas_info_t initialNasMsg; nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id); // 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; + if (!initialNasMsg.nas_data) { + LOG_E(NR_RRC, "Failed to complete RRCSetup. NAS InitialUEMessage message not found.\n"); + return; + } } else { - nas_msg = nr_nas_attach_req_imsi_dummy_NSA_case; - nas_msg_length = sizeof(nr_nas_attach_req_imsi_dummy_NSA_case); + initialNasMsg.length = sizeof(nr_nas_attach_req_imsi_dummy_NSA_case); + initialNasMsg.nas_data = malloc_or_fail(initialNasMsg.length); + memcpy(initialNasMsg.nas_data, nr_nas_attach_req_imsi_dummy_NSA_case, initialNasMsg.length); } + // Encode RRCSetupComplete + int size = do_RRCSetupComplete(buffer, + sizeof(buffer), + Transaction_id, + rrc->selected_plmn_identity, + (const uint32_t)initialNasMsg.length, + (const char*)initialNasMsg.nas_data); + // Free dynamically allocated data (heap allocated in both SA and NSA) + free(initialNasMsg.nas_data); - int size = do_RRCSetupComplete(buffer, sizeof(buffer), Transaction_id, rrc->selected_plmn_identity, nas_msg_length, nas_msg); LOG_I(NR_RRC, "[UE %ld][RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCSetupComplete (bytes%d)\n", rrc->ue_id, size); int srb_id = 1; // RRC setup complete on SRB1 LOG_D(NR_RRC, "[RRC_UE %ld] PDCP_DATA_REQ/%d Bytes RRCSetupComplete ---> %d\n", rrc->ue_id, size, srb_id); - nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } From 48a307e172b508240a15e8ab5a7c60a24b2b5e1e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 5 Jun 2024 11:24:13 +0200 Subject: [PATCH 6/7] Use 5G-S-TMSI in RRC connection setup procedures * Use the 5G-S-TMSI stored in RRC to be used as UE identity * Use 5G-S-TMSI part 1 in RRCSetupRequest encoding (TS 38.331 clause 5.3.3.3) * Set the ng-5G-S-TMSI-Value in RRCSetupComplete to ng-5G-S-TMSI-Part2 (5.3.3.4 of 3GPP TS 38.331) * current and only scenario: RRCSetup is received in response to an RRCSetupRequest --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 52 ++++++++++++++++++++++++----- openair2/RRC/NR/MESSAGES/asn1_msg.h | 4 ++- openair2/RRC/NR_UE/rrc_UE.c | 6 +++- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index b66625e6b2..e3df557d3d 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -765,7 +765,7 @@ int do_RRCReconfiguration(const gNB_RRC_UE_t *UE, return((enc_rval.encoded+7)/8); } -int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv) +int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI) { NR_UL_CCCH_Message_t ul_ccch_msg = {0}; ul_ccch_msg.message.present = NR_UL_CCCH_MessageType_PR_c1; @@ -773,24 +773,34 @@ int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv) c1->present = NR_UL_CCCH_MessageType__c1_PR_rrcSetupRequest; asn1cCalloc(c1->choice.rrcSetupRequest, rrcSetupRequest); - if (1) { + if (fiveG_S_TMSI == UINT64_MAX) { + /* set the ue-Identity to a random value */ rrcSetupRequest->rrcSetupRequest.ue_Identity.present = NR_InitialUE_Identity_PR_randomValue; BIT_STRING_t *str = &rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.randomValue; str->size = 5; str->bits_unused = 1; - str->buf = CALLOC(1, str->size); + str->buf = calloc_or_fail(str->size, sizeof(str->buf[0])); str->buf[0] = rv[0]; str->buf[1] = rv[1]; str->buf[2] = rv[2]; str->buf[3] = rv[3]; str->buf[4] = rv[4] & 0xfe; } else { + uint64_t fiveG_S_TMSI_part1 = fiveG_S_TMSI & ((1ULL << 39) - 1); + /** set the ue-Identity to ng-5G-S-TMSI-Part1 + * ng-5G-S-TMSI-Part1: the rightmost 39 bits of 5G-S-TMSI + * BIT STRING (SIZE (39)) - 3GPP TS 38.331 */ + LOG_D(NR_RRC, "5G-S-TMSI: %lu, set the ue-Identity to ng-5G-S-TMSI-Part1 %lu\n", fiveG_S_TMSI, fiveG_S_TMSI_part1); rrcSetupRequest->rrcSetupRequest.ue_Identity.present = NR_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1; BIT_STRING_t *str = &rrcSetupRequest->rrcSetupRequest.ue_Identity.choice.ng_5G_S_TMSI_Part1; - str->size = 1; - str->bits_unused = 0; - str->buf = CALLOC(1, str->size); - str->buf[0] = 0x12; + str->size = 5; + str->bits_unused = 1; + str->buf = calloc_or_fail(str->size, sizeof(str->buf[0])); + str->buf[0] = (fiveG_S_TMSI_part1 >> 31) & 0xff; + str->buf[1] = (fiveG_S_TMSI_part1 >> 23) & 0xff; + str->buf[2] = (fiveG_S_TMSI_part1 >> 15) & 0xff; + str->buf[3] = (fiveG_S_TMSI_part1 >> 7) & 0xff; + str->buf[4] = (fiveG_S_TMSI_part1 << 1) & 0xff; } rrcSetupRequest->rrcSetupRequest.establishmentCause = NR_EstablishmentCause_mo_Signalling; //EstablishmentCause_mo_Data; @@ -872,6 +882,8 @@ int do_RRCSetupComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id, uint8_t sel_plmn_id, + bool is_rrc_connection_setup, + uint64_t fiveG_s_tmsi, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) { @@ -887,7 +899,31 @@ int do_RRCSetupComplete(uint8_t *buffer, NR_RRCSetupComplete_IEs_t *ies = RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete; ies->selectedPLMN_Identity = sel_plmn_id; ies->registeredAMF = NULL; - ies->ng_5G_S_TMSI_Value = NULL; + /* RRCSetup is received in response to an RRCSetupRequest + * set the ng-5G-S-TMSI-Value to ng-5G-S-TMSI-Part2 + * i.e. the leftmost 9 bits of 5G-S-TMSI (5.3.3.4 of 3GPP TS 38.331) */ + if (fiveG_s_tmsi != UINT64_MAX) { + if (is_rrc_connection_setup) { + ies->ng_5G_S_TMSI_Value = calloc_or_fail(1, sizeof(*ies->ng_5G_S_TMSI_Value)); + ies->ng_5G_S_TMSI_Value->present = NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI_Part2; + BIT_STRING_t *str = &ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI_Part2; + str->size = 2; + str->bits_unused = 7; + str->buf = calloc_or_fail(str->size, sizeof(str->buf[0])); + uint16_t fiveG_s_tmsi_part2 = (fiveG_s_tmsi >> 39) & ((1ULL << 9) - 1); + str->buf[0] = (fiveG_s_tmsi_part2 >> (8 - str->bits_unused)) & 0xFF; + str->buf[1] = (fiveG_s_tmsi_part2 << str->bits_unused) & 0xFF; + LOG_D(NR_RRC, "5G-S-TMSI part 2 %d in RRCSetupComplete (5G-S-TMSI %ld)\n", fiveG_s_tmsi_part2, fiveG_s_tmsi); + } else { + ies->ng_5G_S_TMSI_Value = CALLOC(1, sizeof(struct NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value)); + ies->ng_5G_S_TMSI_Value->present = NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI; + FIVEG_S_TMSI_TO_BIT_STRING(fiveG_s_tmsi, &ies->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI); + LOG_D(NR_RRC, "5G-S-TMSI %lu in RRCSetupComplete\n", fiveG_s_tmsi); + } + } else { + LOG_D(NR_RRC, "5G-S-TMSI is not available!\n"); + ies->ng_5G_S_TMSI_Value = NULL; + } memset(&ies->dedicatedNAS_Message,0,sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(&ies->dedicatedNAS_Message, dedicatedInfoNAS, dedicatedInfoNASLength); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index d7642ca663..a6c5e25aec 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -119,12 +119,14 @@ int do_RRCSetupComplete(uint8_t *buffer, size_t buffer_size, const uint8_t Transaction_id, uint8_t sel_plmn_id, + bool is_rrc_connection_setup, + uint64_t fiveG_S_TMSI, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS); int do_NR_HandoverPreparationInformation(const uint8_t *uecap_buf, int uecap_buf_size, uint8_t *buf, int buf_size); -int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv); +int do_RRCSetupRequest(uint8_t *buffer, size_t buffer_size, uint8_t *rv, uint64_t fiveG_S_TMSI_part1); int do_NR_RRCReconfigurationComplete_for_nsa(uint8_t *buffer, size_t buffer_size, NR_RRC_TransactionIdentifier_t Transaction_id); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 9575fa1940..6b8a12e4cc 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -276,7 +276,7 @@ static void nr_rrc_ue_prepare_RRCSetupRequest(NR_UE_RRC_INST_t *rrc) } uint8_t buf[1024]; - int len = do_RRCSetupRequest(buf, sizeof(buf), rv); + int len = do_RRCSetupRequest(buf, sizeof(buf), rv, rrc->fiveG_S_TMSI); nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buf, len); } @@ -1140,13 +1140,17 @@ static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const initialNasMsg.nas_data = malloc_or_fail(initialNasMsg.length); memcpy(initialNasMsg.nas_data, nr_nas_attach_req_imsi_dummy_NSA_case, initialNasMsg.length); } + // Encode RRCSetupComplete int size = do_RRCSetupComplete(buffer, sizeof(buffer), Transaction_id, rrc->selected_plmn_identity, + rrc->ra_trigger == RRC_CONNECTION_SETUP, + rrc->fiveG_S_TMSI, (const uint32_t)initialNasMsg.length, (const char*)initialNasMsg.nas_data); + // Free dynamically allocated data (heap allocated in both SA and NSA) free(initialNasMsg.nas_data); From 89ca89ea4b9bc52c7612f5b251aa8673c479b56e Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 22 Jul 2024 16:06:29 +0200 Subject: [PATCH 7/7] Address integrity failure after UE reconnects from RRC IDLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After a new connection from RRC IDLE, an integrity failure occurs. This commit is addressing this issue to pass the integrity check. * Reset ciphering and integrity algorithms when going into RRC IDLE * Use uplink NAS COUNT in Registration Request for initial KgNB derivation * Temporarily deriving UP protection keys in Registration Request * Note: AS SMC handling should be done according to 33.501 ยง6.8.1.1.2.2 --- openair2/RRC/NR_UE/rrc_UE.c | 2 ++ openair3/NAS/NR_UE/nr_nas_msg.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 6b8a12e4cc..f61ce49494 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2562,6 +2562,8 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, // discard the keys (only kgnb is stored) memset(rrc->kgnb, 0, sizeof(rrc->kgnb)); + rrc->integrityProtAlgorithm = 0; + rrc->cipheringAlgorithm = 0; // release all radio resources, including release of the RLC entity, // the MAC configuration and the associated PDCP entity diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index f78caf39f9..64a541aa78 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -663,6 +663,12 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas, nasmessagecontainercontents->length = mm_msg_encode(&full_mm, nasmessagecontainercontents->value, size_nct); size += (nasmessagecontainercontents->length + 2); rr->presencemask |= REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT; + // Workaround to pass integrity in RRC_IDLE + uint8_t *kamf = nas->security.kamf; + uint8_t *kgnb = nas->security.kgnb; + derive_kgnb(kamf, nas->security.nas_count_ul, kgnb); + int nas_itti_kgnb_refresh_req(instance_t instance, const uint8_t kgnb[32]); + nas_itti_kgnb_refresh_req(nas->UE_id, nas->security.kgnb); } // Allocate buffer (including NAS message container size) initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data));