pespin has uploaded this change for review.

View Change

Move ConnHdlr logic to its own file

Similar to what we do in other testsuites, since we start to have
considrable amount of logic.

Change-Id: If7edf8ee63c71fbf949e2d340cf3881fd8e3ba41
---
M 5gc/C5G_Tests.ttcn
A 5gc/ConnHdlr.ttcn
2 files changed, 379 insertions(+), 321 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/52/40752/1
diff --git a/5gc/C5G_Tests.ttcn b/5gc/C5G_Tests.ttcn
index 3b84a58..5fc5d4d 100644
--- a/5gc/C5G_Tests.ttcn
+++ b/5gc/C5G_Tests.ttcn
@@ -45,6 +45,8 @@
import from NG_NAS_Functions all;
import from NG_CryptoFunctions all;

+import from ConnHdlr all;
+
/* (maximum) number of emulated eNBs */
const integer NUM_NGRAN := 1;

@@ -68,35 +70,13 @@
charstring mp_local_gtpu_ip := "127.0.0.1";
}

-/* parameters of emulated gNB / ng-eNB */
-type record NGRANParams {
- GlobalRANNodeID global_ngran_id,
- NGRAN_CGI cell_identity,
- SupportedTAList supported_ta_list
-}
-
-/* parameters of emulated UE */
-type record UeParams {
- HEX15n imsi,
- HEX16n imeisv,
- octetstring usim_key,
- octetstring usim_opc,
- charstring ran_gtpu_ip,
- OCT4 ran_gtpu_teid,
- charstring cn_gtpu_ip optional,
- OCT4 cn_gtpu_teid optional,
- charstring ue_ip optional,
- OCT32 kausf optional,
- OCT32 kseaf optional,
- OCT32 kamf optional
-}
-
template (value) UeParams ts_UeParams(integer imsi_suffix) :=
{
imsi := f_concat_pad(lengthof(mp_imsi), substr(mp_imsi, 0, lengthof(mp_imsi) - 6), imsi_suffix),
imeisv := f_rnd_imeisv(),
usim_key := mp_usim_key,
usim_opc := mp_usim_opc,
+ apn := mp_apn,
ran_gtpu_ip := mp_local_gtpu_ip,
ran_gtpu_teid := int2oct(imsi_suffix, 4),
cn_gtpu_ip := omit,
@@ -119,21 +99,6 @@
var UeParams g_ue_pars[NUM_UE];
}

-type component ConnHdlr extends NGAP_ConnHdlr {
- var ConnHdlrPars g_pars;
-}
-
-type record ConnHdlrPars {
- /* copied over from MTC_CT on start of component */
- NGRANParams ngran_pars[NUM_NGRAN],
- /* copied over from MTC_CT on start of component */
- UeParams ue_pars,
- /* currently used 5GC (index into ngran_pars, NGAP, ...) */
- integer c5g_idx,
- /* Currently set KSI */
- NAS_KeySetIdentifier kset_id
-}
-
/* send incoming unit data messages (like reset) to global NGAP_UNIT port */
private function NGapForwardUnitdataCallback(NGAP_PDU msg)
runs on NGAP_Emulation_CT return template NGAP_PDU {
@@ -213,8 +178,6 @@
return pars;
}

-type function void_fn() runs on ConnHdlr;
-
/* start a connection handler with given parameters */
private function f_start_handler_with_pars(void_fn fn, ConnHdlrPars pars, integer ngap_idx := 0)
runs on MTC_CT return ConnHdlr {
@@ -245,44 +208,6 @@
fn.apply();
}

-private template (value) NGAP_IEs.TAI ts_ngran_NGAP_TAI(NGRANParams ngran_pars) := {
- pLMNIdentity := ngran_pars.global_ngran_id.globalGNB_ID.pLMNIdentity,
- tAC := ngran_pars.supported_ta_list[0].tAC,
- iE_Extensions := omit
-}
-
-private function f_imsi_plmn_id() runs on ConnHdlr return PLMNIdentity {
- var hexstring imsi := g_pars.ue_pars.imsi;
- var GsmMcc mcc := substr(imsi, 0, 3);
- var GsmMnc mnc := substr(imsi, 3, 2);
- return f_enc_mcc_mnc(mcc, mnc);
-}
-
-private function f_SUCI_IMSI() runs on ConnHdlr return octetstring {
- var hexstring imsi := g_pars.ue_pars.imsi;
- var PLMNIdentity plmn_id := f_imsi_plmn_id();
- var octetstring imsi_suffix := imsi_hex2oct(substr(imsi, lengthof(imsi) - 10, 10));
- return plmn_id & '21430001'O & imsi_suffix;
-}
-
-private function f_UE_SecurityCapability() runs on ConnHdlr return NG_UE_SecurityCapability {
- var template (value) NG_UE_SecurityCapability ue_sec_cap;
- ue_sec_cap := cs_NG_UE_SecurityCapabilityTLV(ngeaCap := '80'O, /* ONLY NEA0 (no encryption) for now */
- ngiaCap := '40'O /* ONLY NIA1 supported */);
- return valueof(ue_sec_cap);
-}
-
-private function f_ULI() runs on ConnHdlr return UserLocationInformation {
- var template (value) UserLocationInformation p_ueLocInf
- p_ueLocInf := m_uPTransportLayerInformation_userLocationInformationNR(
- m_userLocationInformationNR(
- g_pars.ngran_pars[g_pars.c5g_idx].cell_identity.nR_CGI,
- ts_ngran_NGAP_TAI(g_pars.ngran_pars[g_pars.c5g_idx])
-
- ));
- return valueof(p_ueLocInf);
-}
-
private function f_ngap_setup(integer idx := 0, template (omit) NGAP_IEs.Cause cause := omit) runs on MTC_CT {
var template (present) NGAP_IEs.Cause exp_cause := ?;
var boolean exp_fail := false;
@@ -323,249 +248,6 @@
}
}

-private function f_tr_ConnHdlr_kset_id() runs on ConnHdlr return template (present) NAS_KeySetIdentifier {
- /* KSI not yet set, expect whatever assignment from network: */
- if (g_pars.kset_id.nasKeySetId == tsc_NasKsi_NoKey) {
- return cr_NAS_KeySetIdentifier(?, ?);
- } else {
- /* Expect specific kset_id. Upon transmitting it UE->Network, f_attach()
- * has updated it to the expected value. */
- return g_pars.kset_id;
- }
-}
-
-/* 3GPP TS 24.501 5.4.1.3.2, 3GPP TS 33.501 6.1.3.2 */
-private altstep as_ngap_handle_auth(boolean allow_resync := true) runs on ConnHdlr {
- var NG_NAS_DL_Message_Type rx_nas;
- var template (present) NAS_KeySetIdentifier kset_id := f_tr_ConnHdlr_kset_id();
- [] NGAP.receive(cr_NG_AUTHENTICATION_REQUEST) -> value rx_nas {
- var integer ret;
- var integer my_sqn := 0; /* TODO: move to a ConnHdlr state attribute? */
- var OCT16 rand := bit2oct(rx_nas.authentication_Request.rand.randValue);
- var OCT16 autn := bit2oct(rx_nas.authentication_Request.autn.aUTN);
- var OCT2 abba := rx_nas.authentication_Request.abba.abbaValue;
- var OCT16 ik;
- var OCT16 ck;
- var OCT8 res;
- var OCT14 auts;
-
- g_pars.kset_id := rx_nas.authentication_Request.ngNasKeySetId;
-
- ret := f_milenage_check(g_pars.ue_pars.usim_key,
- g_pars.ue_pars.usim_opc,
- int2oct(my_sqn, 8),
- rand, autn, ik, ck, res, auts);
- if (ret == -1) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("fx_milenage_check() failed! -1"));
- }
- if (ret == -2) {
- if (not allow_resync) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("fx_milenage_check() unexpected Resync!"));
- }
- log("Milenage: RX-SQN differs from SIM SQN: Re-Sync! AUTS=", auts);
- /* 3GPP TS 24.501 5.4.1.3.6 d) */
- NGAP.send(cs_NG_AUTHENTICATION_FAILURE(cs_GMM_GSM_Cause(omit, int2bit(21, 8)),
- cs_AuthFailParam(oct2bit(auts))));
- as_ngap_handle_auth(allow_resync := false);
- return;
- }
-
- var octetstring ssn := f_NG_NAS_ServingNetworkName_OCT(f_imsi_plmn_id(), omit);
- g_pars.ue_pars.kausf := f_kdf_kausf(ck, ik, ssn, autn);
- g_pars.ue_pars.kseaf := f_kdf_kseaf(g_pars.ue_pars.kausf, ssn);
- g_pars.ue_pars.kamf := f_kdf_kamf(g_pars.ue_pars.kseaf, char2oct(hex2str(g_pars.ue_pars.imsi)), abba);
-
- var NGAPEM_Config cfg := {
- set_nas_keys := {
- k_nas_int := f_kdf_ng_nas_int(g_pars.ue_pars.kamf, NG_NAS_ALG_IP_NIA1),
- k_nas_enc := f_kdf_ng_nas_enc(g_pars.ue_pars.kamf, NG_NAS_ALG_ENC_NEA0)
- }
- };
- NGAP.send(cfg);
-
- /* Derive (X)RES* from (X)RES, 3GPP TS 33.501 A.4 */
- var OCT16 res_star := f_kdf_xres_star(ssn, ck, ik, rand, res);
- NGAP.send(cs_NG_AUTHENTICATION_RESPONSE(cs_AuthenticationResponseParameter(oct2bit(res_star))));
- }
-}
-
-private altstep as_ngap_handle_sec_mode() runs on ConnHdlr {
- var NGAPEM_Config cfg;
- var NG_NAS_DL_Message_Type rx_nas;
- /* Make sure network selected specific algos we requested: */
- var template (present) NG_UE_SecurityCapability ue_sec_cap :=
- cr_NG_UE_SecurityCapabilityLV(ngeaCap := '80'O, /* ONLY NEA0 (no encryption) for now */
- ngiaCap := '40'O /* ONLY NIA1 supported */);
-
- [] NGAP.receive(cr_NG_SECURITY_MODE_COMMAND(p_UECap := ue_sec_cap)) -> value rx_nas {
- /* Configure integrity protection: */
- cfg := {
- set_nas_alg_int := NG_NAS_ALG_IP_NIA1
- };
- NGAP.send(cfg);
- /* Configure Ciphering: */
- cfg := {
- set_nas_alg_enc := NG_NAS_ALG_ENC_NEA0
- };
- NGAP.send(cfg);
-
- var template (value) NG_NAS_UL_Message_Type nas_ul_msg;
- var NAS_PDU nas_pdu;
- nas_ul_msg := cs_NG_REGISTRATION_REQUEST(cs_RegistrationType(tsc_NG_RegistrationInitial, '1'B),
- g_pars.kset_id.nasKeySetId,
- g_pars.kset_id.tsc,
- cs_NG_MobileIdentitySUCI('0000'B /* Type IMSI */,
- f_SUCI_IMSI()),
- p_UESecurityCap := f_UE_SecurityCapability());
- nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg));
- NGAP.send(cs_NG_SECURITY_MODE_COMPLETE(cs_NG_MobileIdentityTLV_IMEISV(hex2oct(g_pars.ue_pars.imeisv)),
- cs_ReplayedNASMessageContainerTLV(nas_pdu)));
- }
-}
-
-private altstep as_ngap_handle_configuration_update() runs on ConnHdlr {
- var NG_NAS_DL_Message_Type rx_nas;
-
- [] NGAP.receive(cr_NG_CONFIGURATION_UPDATE_COMMAND) -> value rx_nas {
- NGAP.send(cs_NG_CONFIGURATION_UPDATE_COMPLETE);
- }
-}
-
-/* Handle a PDUSessionResourceSetupRequestTransfer contained inside NGAP InitialContextSetupRequest and return a Result for InitialContextSetupResponse */
-private function f_pdu_handle_session_resource_setup_item(PDUSessionResourceSetupItemCxtReq req) runs on ConnHdlr return PDUSessionResourceSetupItemCxtRes
-{
- var PDUSessionResourceSetupItemCxtRes resp;
- var octetstring setup_trans_enc;
- var NGAP_IEs.PDUSessionResourceSetupRequestTransfer setup_req_transf;
- var NGAP_IEs.PDUSessionResourceSetupResponseTransfer setup_resp_transf;
- var template (value) UPTransportLayerInformation utla;
- var template (value) QosFlowPerTNLInformation qos;
-
- /* Parse PDUSessionResourceSetupRequestTransfer contained inside InitialContextSetupRequest's PDUSessionResourceSetup Item: */
- setup_req_transf := dec_NGAP_PDUSessionResourceSetupRequestTransfer(req.pDUSessionResourceSetupRequestTransfer);
- for (var integer i := 0; i < lengthof(setup_req_transf.protocolIEs); i := i + 1) {
- if (setup_req_transf.protocolIEs[i].id == id_UL_NGU_UP_TNLInformation) {
- var UPTransportLayerInformation utli := setup_req_transf.protocolIEs[i].value_.uPTransportLayerInformation;
- g_pars.ue_pars.cn_gtpu_ip := f_inet_ntoa(bit2oct(utli.gTPTunnel.transportLayerAddress));
- g_pars.ue_pars.cn_gtpu_teid := utli.gTPTunnel.gTP_TEID;
- }
- }
-
- /* Prepare Response for it: */
- utla := m_uPTransportLayerInformation_gTPTunnel(
- m_gTPTunnel(p_tla := oct2bit(f_inet_addr(g_pars.ue_pars.ran_gtpu_ip)),
- p_gtp_teid := g_pars.ue_pars.ran_gtpu_teid));
- qos := m_qosFlowPerTNLInformation(utla, { m_associatedQosFlowItem(1) });
- setup_resp_transf := valueof(m_pDUSessionResourceSetupResponseTransfer(qos));
- setup_trans_enc := enc_NGAP_PDUSessionResourceSetupResponseTransfer(setup_resp_transf)
- resp := valueof(m_pDUSessionResourceSetupItemCxtRes(req.pDUSessionID, setup_trans_enc));
- return resp;
-}
-
-private function f_pdu_handle_session_resource_setup_list(PDUSessionResourceSetupListCxtReq li_req) runs on ConnHdlr return PDUSessionResourceSetupListCxtRes
-{
- var PDUSessionResourceSetupListCxtRes li_resp;
- for (var integer i := 0; i < lengthof(li_req); i := i + 1) {
- var PDUSessionResourceSetupItemCxtRes it_resp;
- it_resp := f_pdu_handle_session_resource_setup_item(li_req[i]);
- if (i == 0) { /* min 1 item in list doesn't allow previously allocating an empty list */
- li_resp := { it_resp };
- } else {
- li_resp := li_resp & { it_resp };
- }
- }
- return li_resp;
-}
-
-private altstep as_ngap_handle_InitialCtxReq_withPDUSessionList() runs on ConnHdlr {
- var NGAP_PDU rx_ngap;
-
- [] NGAP.receive(mw_ngap_initMsg(mw_n2_InitialContextSetupRequest_withPDUSessionList)) -> value rx_ngap {
- var AMF_UE_NGAP_ID amf_id := valueof(f_NGAP_get_AMF_UE_NGAP_ID(rx_ngap));
- var RAN_UE_NGAP_ID ran_id := valueof(f_NGAP_get_RAN_UE_NGAP_ID(rx_ngap));
- var InitialContextSetupRequest ctx_setup_req := rx_ngap.initiatingMessage.value_.initialContextSetupRequest;
- var PDUSessionResourceSetupListCxtRes resources;
-
- for (var integer i := 0; i < lengthof(ctx_setup_req.protocolIEs); i := i + 1) {
- if (ctx_setup_req.protocolIEs[i].id != id_PDUSessionResourceSetupListCxtReq) {
- continue;
- }
- var PDUSessionResourceSetupListCxtReq li := ctx_setup_req.protocolIEs[i].value_.pDUSessionResourceSetupListCxtReq;
- resources := f_pdu_handle_session_resource_setup_list(li);
- }
- NGAP.send(m_ngap_succMsg(m_n2_InitialContextSetupResponse(amf_id, ran_id, resources)));
- }
-}
-
-private function f_pdu_sess_establish() runs on ConnHdlr {
- var template (value) NG_NAS_UL_Message_Type nas_ul_msg;
- var NAS_PDU nas_pdu;
- var NG_NAS_DL_Message_Type rx_nas, inner_nas;
-
- nas_ul_msg := cs_NG_PDU_SESSION_ESTABLISHMENT_REQUEST(cs_NG_PDU_SessionIdV('01'O), '01'O,
- p_IntegrityProtMaxDataRate := cs_IntegrityProtMaxDataRateV('FF'O, 'FF'O),
- p_PDU_SessionType := cs_PDU_SessionTypeTV('001'B), /* IPv4 */
- p_SSC_Mode := cs_SSC_ModeTV('001'B));
- nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg));
- nas_ul_msg := cs_NG_UL_NAS_TRANSPORT(cs_PayloadContainerType(tsc_PayloadContainerESMMsg),
- cs_PayloadContainerLV(nas_pdu),
- p_PDU_SessionId := cs_NG_PDU_SessionIdTV('01'O),
- p_RequestType := cs_NG_Request_TypeTV('001'B),
- p_DNN := cs_DNN_TLV(f_enc_dns_hostname(mp_apn)));
- NGAP.send(nas_ul_msg);
- as_ngap_handle_InitialCtxReq_withPDUSessionList();
-
- /* PDU Session Establishment Accept: This DL NAS arrives contained in InitialCtxReq handled above: */
- NGAP.receive(cr_NG_DL_NAS_TRANSPORT) -> value rx_nas;
- inner_nas := f_dec_NG_NAS_DL_Message_Payload_Container(rx_nas.dl_Nas_Transport.payloadContainerType.container,
- rx_nas.dl_Nas_Transport.payload.payload);
- g_pars.ue_pars.ue_ip := f_inet_ntoa(inner_nas.pdu_Session_Establishment_Accept.pduAddress.adressInfo);
- log("5GC assigned CN GTPU Address: ", g_pars.ue_pars.cn_gtpu_ip, " TEID: ", g_pars.ue_pars.cn_gtpu_teid);
- log("5GC assigned UE IP address: ", g_pars.ue_pars.ue_ip);
-}
-
-private function f_register() runs on ConnHdlr {
- var template (value) NGAP_PDU tx_pdu;
- var template (value) NG_NAS_UL_Message_Type nas_ul_msg;
- var NAS_PDU nas_pdu;
- var NG_NAS_DL_Message_Type rx_nas;
-
- nas_ul_msg := cs_NG_REGISTRATION_REQUEST(cs_RegistrationType(tsc_NG_RegistrationInitial, '1'B),
- g_pars.kset_id.nasKeySetId,
- g_pars.kset_id.tsc,
- cs_NG_MobileIdentitySUCI('0000'B /* Type IMSI */,
- f_SUCI_IMSI()),
- p_UESecurityCap := f_UE_SecurityCapability());
- nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg));
- tx_pdu := m_ngap_initMsg(m_n2_initialUeMessage(g_pars.c5g_idx,
- nas_pdu, /* Registration request */
- f_ULI(),
- mo_Signalling));
- NGAP.send(tx_pdu);
-
- /* Expect updated KSI from network following 5G Core standards
- *(open5gs.git 70310979c58fe186e9eaa06bec9d9a31f24ff7a1): */
- if (g_pars.kset_id.nasKeySetId != tsc_NasKsi_NoKey) {
- if (g_pars.kset_id.nasKeySetId == '110'B) {
- g_pars.kset_id.nasKeySetId := '000'B;
- } else {
- g_pars.kset_id.nasKeySetId := int2bit(bit2int(g_pars.kset_id.nasKeySetId) + 1, 3);
- }
- }
-
- as_ngap_handle_auth();
- as_ngap_handle_sec_mode();
-
- NGAP.receive(cr_NG_REGISTRATION_ACCEPT) -> value rx_nas;
- NGAP.send(cs_NG_REGISTRATION_COMPLETE);
-
- as_ngap_handle_configuration_update();
-
- f_pdu_sess_establish();
-}
-
/* NG Setup procedure to 5GC using a Global gNB ID containing unknown/foreign PLMN.
* Related: https://github.com/open5gs/open5gs/issues/3544 */
testcase TC_ng_setup_unknown_global_gnb_id_plmn() runs on MTC_CT {
diff --git a/5gc/ConnHdlr.ttcn b/5gc/ConnHdlr.ttcn
new file mode 100644
index 0000000..0f06447
--- /dev/null
+++ b/5gc/ConnHdlr.ttcn
@@ -0,0 +1,376 @@
+/* 5GC (55G Core) test suite in TTCN-3, ConnHdlr
+ * (C) 2025 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module ConnHdlr {
+
+import from General_Types all;
+import from Native_Functions all;
+import from IPL4asp_Types all;
+import from Misc_Helpers all;
+
+import from Osmocom_Types all;
+import from GSM_Types all;
+
+import from DNS_Helpers all;
+
+import from Milenage_Functions all;
+
+import from NGAP_PDU_Descriptions all;
+import from NGAP_IEs all;
+import from NGAP_PDU_Contents all;
+import from NGAP_Constants all;
+
+import from NGAP_Types all;
+import from NGAP_Pixits all;
+import from NGAP_Templates all;
+import from NGAP_Functions all;
+import from NGAP_Emulation all;
+
+import from NAS_CommonTypeDefs all;
+import from NAS_CommonTemplates all;
+import from NG_NAS_Common all;
+import from NG_NAS_TypeDefs all;
+import from NG_NAS_MsgContainers all;
+import from NG_NAS_Templates all;
+
+import from NG_NAS_Osmo_Templates all;
+import from NG_NAS_Functions all;
+import from NG_CryptoFunctions all;
+
+/* (maximum) number of emulated eNBs */
+const integer NUM_NGRAN := 1;
+
+/* (maximum) number of emulated UEs */
+const integer NUM_UE := 1;
+
+/* parameters of emulated gNB / ng-eNB */
+type record NGRANParams {
+ GlobalRANNodeID global_ngran_id,
+ NGRAN_CGI cell_identity,
+ SupportedTAList supported_ta_list
+}
+
+/* parameters of emulated UE */
+type record UeParams {
+ HEX15n imsi,
+ HEX16n imeisv,
+ octetstring usim_key,
+ octetstring usim_opc,
+ charstring apn,
+ charstring ran_gtpu_ip,
+ OCT4 ran_gtpu_teid,
+ charstring cn_gtpu_ip optional,
+ OCT4 cn_gtpu_teid optional,
+ charstring ue_ip optional,
+ OCT32 kausf optional,
+ OCT32 kseaf optional,
+ OCT32 kamf optional
+}
+
+type record ConnHdlrPars {
+ /* copied over from MTC_CT on start of component */
+ NGRANParams ngran_pars[NUM_NGRAN],
+ /* copied over from MTC_CT on start of component */
+ UeParams ue_pars,
+ /* currently used 5GC (index into ngran_pars, NGAP, ...) */
+ integer c5g_idx,
+ /* Currently set KSI */
+ NAS_KeySetIdentifier kset_id
+}
+
+type component ConnHdlr extends NGAP_ConnHdlr {
+ var ConnHdlrPars g_pars;
+}
+
+type function void_fn() runs on ConnHdlr;
+
+private template (value) NGAP_IEs.TAI ts_ngran_NGAP_TAI(NGRANParams ngran_pars) := {
+ pLMNIdentity := ngran_pars.global_ngran_id.globalGNB_ID.pLMNIdentity,
+ tAC := ngran_pars.supported_ta_list[0].tAC,
+ iE_Extensions := omit
+}
+
+private function f_imsi_plmn_id() runs on ConnHdlr return PLMNIdentity {
+ var hexstring imsi := g_pars.ue_pars.imsi;
+ var GsmMcc mcc := substr(imsi, 0, 3);
+ var GsmMnc mnc := substr(imsi, 3, 2);
+ return f_enc_mcc_mnc(mcc, mnc);
+}
+
+private function f_SUCI_IMSI() runs on ConnHdlr return octetstring {
+ var hexstring imsi := g_pars.ue_pars.imsi;
+ var PLMNIdentity plmn_id := f_imsi_plmn_id();
+ var octetstring imsi_suffix := imsi_hex2oct(substr(imsi, lengthof(imsi) - 10, 10));
+ return plmn_id & '21430001'O & imsi_suffix;
+}
+
+private function f_UE_SecurityCapability() runs on ConnHdlr return NG_UE_SecurityCapability {
+ var template (value) NG_UE_SecurityCapability ue_sec_cap;
+ ue_sec_cap := cs_NG_UE_SecurityCapabilityTLV(ngeaCap := '80'O, /* ONLY NEA0 (no encryption) for now */
+ ngiaCap := '40'O /* ONLY NIA1 supported */);
+ return valueof(ue_sec_cap);
+}
+
+private function f_ULI() runs on ConnHdlr return UserLocationInformation {
+ var template (value) UserLocationInformation p_ueLocInf
+ p_ueLocInf := m_uPTransportLayerInformation_userLocationInformationNR(
+ m_userLocationInformationNR(
+ g_pars.ngran_pars[g_pars.c5g_idx].cell_identity.nR_CGI,
+ ts_ngran_NGAP_TAI(g_pars.ngran_pars[g_pars.c5g_idx])
+
+ ));
+ return valueof(p_ueLocInf);
+}
+
+private function f_tr_ConnHdlr_kset_id() runs on ConnHdlr return template (present) NAS_KeySetIdentifier {
+ /* KSI not yet set, expect whatever assignment from network: */
+ if (g_pars.kset_id.nasKeySetId == tsc_NasKsi_NoKey) {
+ return cr_NAS_KeySetIdentifier(?, ?);
+ } else {
+ /* Expect specific kset_id. Upon transmitting it UE->Network, f_attach()
+ * has updated it to the expected value. */
+ return g_pars.kset_id;
+ }
+}
+
+/* 3GPP TS 24.501 5.4.1.3.2, 3GPP TS 33.501 6.1.3.2 */
+private altstep as_ngap_handle_auth(boolean allow_resync := true) runs on ConnHdlr {
+ var NG_NAS_DL_Message_Type rx_nas;
+ var template (present) NAS_KeySetIdentifier kset_id := f_tr_ConnHdlr_kset_id();
+ [] NGAP.receive(cr_NG_AUTHENTICATION_REQUEST) -> value rx_nas {
+ var integer ret;
+ var integer my_sqn := 0; /* TODO: move to a ConnHdlr state attribute? */
+ var OCT16 rand := bit2oct(rx_nas.authentication_Request.rand.randValue);
+ var OCT16 autn := bit2oct(rx_nas.authentication_Request.autn.aUTN);
+ var OCT2 abba := rx_nas.authentication_Request.abba.abbaValue;
+ var OCT16 ik;
+ var OCT16 ck;
+ var OCT8 res;
+ var OCT14 auts;
+
+ g_pars.kset_id := rx_nas.authentication_Request.ngNasKeySetId;
+
+ ret := f_milenage_check(g_pars.ue_pars.usim_key,
+ g_pars.ue_pars.usim_opc,
+ int2oct(my_sqn, 8),
+ rand, autn, ik, ck, res, auts);
+ if (ret == -1) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("fx_milenage_check() failed! -1"));
+ }
+ if (ret == -2) {
+ if (not allow_resync) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("fx_milenage_check() unexpected Resync!"));
+ }
+ log("Milenage: RX-SQN differs from SIM SQN: Re-Sync! AUTS=", auts);
+ /* 3GPP TS 24.501 5.4.1.3.6 d) */
+ NGAP.send(cs_NG_AUTHENTICATION_FAILURE(cs_GMM_GSM_Cause(omit, int2bit(21, 8)),
+ cs_AuthFailParam(oct2bit(auts))));
+ as_ngap_handle_auth(allow_resync := false);
+ return;
+ }
+
+ var octetstring ssn := f_NG_NAS_ServingNetworkName_OCT(f_imsi_plmn_id(), omit);
+ g_pars.ue_pars.kausf := f_kdf_kausf(ck, ik, ssn, autn);
+ g_pars.ue_pars.kseaf := f_kdf_kseaf(g_pars.ue_pars.kausf, ssn);
+ g_pars.ue_pars.kamf := f_kdf_kamf(g_pars.ue_pars.kseaf, char2oct(hex2str(g_pars.ue_pars.imsi)), abba);
+
+ var NGAPEM_Config cfg := {
+ set_nas_keys := {
+ k_nas_int := f_kdf_ng_nas_int(g_pars.ue_pars.kamf, NG_NAS_ALG_IP_NIA1),
+ k_nas_enc := f_kdf_ng_nas_enc(g_pars.ue_pars.kamf, NG_NAS_ALG_ENC_NEA0)
+ }
+ };
+ NGAP.send(cfg);
+
+ /* Derive (X)RES* from (X)RES, 3GPP TS 33.501 A.4 */
+ var OCT16 res_star := f_kdf_xres_star(ssn, ck, ik, rand, res);
+ NGAP.send(cs_NG_AUTHENTICATION_RESPONSE(cs_AuthenticationResponseParameter(oct2bit(res_star))));
+ }
+}
+
+private altstep as_ngap_handle_sec_mode() runs on ConnHdlr {
+ var NGAPEM_Config cfg;
+ var NG_NAS_DL_Message_Type rx_nas;
+ /* Make sure network selected specific algos we requested: */
+ var template (present) NG_UE_SecurityCapability ue_sec_cap :=
+ cr_NG_UE_SecurityCapabilityLV(ngeaCap := '80'O, /* ONLY NEA0 (no encryption) for now */
+ ngiaCap := '40'O /* ONLY NIA1 supported */);
+
+ [] NGAP.receive(cr_NG_SECURITY_MODE_COMMAND(p_UECap := ue_sec_cap)) -> value rx_nas {
+ /* Configure integrity protection: */
+ cfg := {
+ set_nas_alg_int := NG_NAS_ALG_IP_NIA1
+ };
+ NGAP.send(cfg);
+ /* Configure Ciphering: */
+ cfg := {
+ set_nas_alg_enc := NG_NAS_ALG_ENC_NEA0
+ };
+ NGAP.send(cfg);
+
+ var template (value) NG_NAS_UL_Message_Type nas_ul_msg;
+ var NAS_PDU nas_pdu;
+ nas_ul_msg := cs_NG_REGISTRATION_REQUEST(cs_RegistrationType(tsc_NG_RegistrationInitial, '1'B),
+ g_pars.kset_id.nasKeySetId,
+ g_pars.kset_id.tsc,
+ cs_NG_MobileIdentitySUCI('0000'B /* Type IMSI */,
+ f_SUCI_IMSI()),
+ p_UESecurityCap := f_UE_SecurityCapability());
+ nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg));
+ NGAP.send(cs_NG_SECURITY_MODE_COMPLETE(cs_NG_MobileIdentityTLV_IMEISV(hex2oct(g_pars.ue_pars.imeisv)),
+ cs_ReplayedNASMessageContainerTLV(nas_pdu)));
+ }
+}
+
+private altstep as_ngap_handle_configuration_update() runs on ConnHdlr {
+ var NG_NAS_DL_Message_Type rx_nas;
+
+ [] NGAP.receive(cr_NG_CONFIGURATION_UPDATE_COMMAND) -> value rx_nas {
+ NGAP.send(cs_NG_CONFIGURATION_UPDATE_COMPLETE);
+ }
+}
+
+/* Handle a PDUSessionResourceSetupRequestTransfer contained inside NGAP InitialContextSetupRequest and return a Result for InitialContextSetupResponse */
+private function f_pdu_handle_session_resource_setup_item(PDUSessionResourceSetupItemCxtReq req) runs on ConnHdlr return PDUSessionResourceSetupItemCxtRes
+{
+ var PDUSessionResourceSetupItemCxtRes resp;
+ var octetstring setup_trans_enc;
+ var NGAP_IEs.PDUSessionResourceSetupRequestTransfer setup_req_transf;
+ var NGAP_IEs.PDUSessionResourceSetupResponseTransfer setup_resp_transf;
+ var template (value) UPTransportLayerInformation utla;
+ var template (value) QosFlowPerTNLInformation qos;
+
+ /* Parse PDUSessionResourceSetupRequestTransfer contained inside InitialContextSetupRequest's PDUSessionResourceSetup Item: */
+ setup_req_transf := dec_NGAP_PDUSessionResourceSetupRequestTransfer(req.pDUSessionResourceSetupRequestTransfer);
+ for (var integer i := 0; i < lengthof(setup_req_transf.protocolIEs); i := i + 1) {
+ if (setup_req_transf.protocolIEs[i].id == id_UL_NGU_UP_TNLInformation) {
+ var UPTransportLayerInformation utli := setup_req_transf.protocolIEs[i].value_.uPTransportLayerInformation;
+ g_pars.ue_pars.cn_gtpu_ip := f_inet_ntoa(bit2oct(utli.gTPTunnel.transportLayerAddress));
+ g_pars.ue_pars.cn_gtpu_teid := utli.gTPTunnel.gTP_TEID;
+ }
+ }
+
+ /* Prepare Response for it: */
+ utla := m_uPTransportLayerInformation_gTPTunnel(
+ m_gTPTunnel(p_tla := oct2bit(f_inet_addr(g_pars.ue_pars.ran_gtpu_ip)),
+ p_gtp_teid := g_pars.ue_pars.ran_gtpu_teid));
+ qos := m_qosFlowPerTNLInformation(utla, { m_associatedQosFlowItem(1) });
+ setup_resp_transf := valueof(m_pDUSessionResourceSetupResponseTransfer(qos));
+ setup_trans_enc := enc_NGAP_PDUSessionResourceSetupResponseTransfer(setup_resp_transf)
+ resp := valueof(m_pDUSessionResourceSetupItemCxtRes(req.pDUSessionID, setup_trans_enc));
+ return resp;
+}
+
+private function f_pdu_handle_session_resource_setup_list(PDUSessionResourceSetupListCxtReq li_req) runs on ConnHdlr return PDUSessionResourceSetupListCxtRes
+{
+ var PDUSessionResourceSetupListCxtRes li_resp;
+ for (var integer i := 0; i < lengthof(li_req); i := i + 1) {
+ var PDUSessionResourceSetupItemCxtRes it_resp;
+ it_resp := f_pdu_handle_session_resource_setup_item(li_req[i]);
+ if (i == 0) { /* min 1 item in list doesn't allow previously allocating an empty list */
+ li_resp := { it_resp };
+ } else {
+ li_resp := li_resp & { it_resp };
+ }
+ }
+ return li_resp;
+}
+
+private altstep as_ngap_handle_InitialCtxReq_withPDUSessionList() runs on ConnHdlr {
+ var NGAP_PDU rx_ngap;
+
+ [] NGAP.receive(mw_ngap_initMsg(mw_n2_InitialContextSetupRequest_withPDUSessionList)) -> value rx_ngap {
+ var AMF_UE_NGAP_ID amf_id := valueof(f_NGAP_get_AMF_UE_NGAP_ID(rx_ngap));
+ var RAN_UE_NGAP_ID ran_id := valueof(f_NGAP_get_RAN_UE_NGAP_ID(rx_ngap));
+ var InitialContextSetupRequest ctx_setup_req := rx_ngap.initiatingMessage.value_.initialContextSetupRequest;
+ var PDUSessionResourceSetupListCxtRes resources;
+
+ for (var integer i := 0; i < lengthof(ctx_setup_req.protocolIEs); i := i + 1) {
+ if (ctx_setup_req.protocolIEs[i].id != id_PDUSessionResourceSetupListCxtReq) {
+ continue;
+ }
+ var PDUSessionResourceSetupListCxtReq li := ctx_setup_req.protocolIEs[i].value_.pDUSessionResourceSetupListCxtReq;
+ resources := f_pdu_handle_session_resource_setup_list(li);
+ }
+ NGAP.send(m_ngap_succMsg(m_n2_InitialContextSetupResponse(amf_id, ran_id, resources)));
+ }
+}
+
+private function f_pdu_sess_establish() runs on ConnHdlr {
+ var template (value) NG_NAS_UL_Message_Type nas_ul_msg;
+ var NAS_PDU nas_pdu;
+ var NG_NAS_DL_Message_Type rx_nas, inner_nas;
+
+ nas_ul_msg := cs_NG_PDU_SESSION_ESTABLISHMENT_REQUEST(cs_NG_PDU_SessionIdV('01'O), '01'O,
+ p_IntegrityProtMaxDataRate := cs_IntegrityProtMaxDataRateV('FF'O, 'FF'O),
+ p_PDU_SessionType := cs_PDU_SessionTypeTV('001'B), /* IPv4 */
+ p_SSC_Mode := cs_SSC_ModeTV('001'B));
+ nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg));
+ nas_ul_msg := cs_NG_UL_NAS_TRANSPORT(cs_PayloadContainerType(tsc_PayloadContainerESMMsg),
+ cs_PayloadContainerLV(nas_pdu),
+ p_PDU_SessionId := cs_NG_PDU_SessionIdTV('01'O),
+ p_RequestType := cs_NG_Request_TypeTV('001'B),
+ p_DNN := cs_DNN_TLV(f_enc_dns_hostname(g_pars.ue_pars.apn)));
+ NGAP.send(nas_ul_msg);
+ as_ngap_handle_InitialCtxReq_withPDUSessionList();
+
+ /* PDU Session Establishment Accept: This DL NAS arrives contained in InitialCtxReq handled above: */
+ NGAP.receive(cr_NG_DL_NAS_TRANSPORT) -> value rx_nas;
+ inner_nas := f_dec_NG_NAS_DL_Message_Payload_Container(rx_nas.dl_Nas_Transport.payloadContainerType.container,
+ rx_nas.dl_Nas_Transport.payload.payload);
+ g_pars.ue_pars.ue_ip := f_inet_ntoa(inner_nas.pdu_Session_Establishment_Accept.pduAddress.adressInfo);
+ log("5GC assigned CN GTPU Address: ", g_pars.ue_pars.cn_gtpu_ip, " TEID: ", g_pars.ue_pars.cn_gtpu_teid);
+ log("5GC assigned UE IP address: ", g_pars.ue_pars.ue_ip);
+}
+
+function f_register() runs on ConnHdlr {
+ var template (value) NGAP_PDU tx_pdu;
+ var template (value) NG_NAS_UL_Message_Type nas_ul_msg;
+ var NAS_PDU nas_pdu;
+ var NG_NAS_DL_Message_Type rx_nas;
+
+ nas_ul_msg := cs_NG_REGISTRATION_REQUEST(cs_RegistrationType(tsc_NG_RegistrationInitial, '1'B),
+ g_pars.kset_id.nasKeySetId,
+ g_pars.kset_id.tsc,
+ cs_NG_MobileIdentitySUCI('0000'B /* Type IMSI */,
+ f_SUCI_IMSI()),
+ p_UESecurityCap := f_UE_SecurityCapability());
+ nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg));
+ tx_pdu := m_ngap_initMsg(m_n2_initialUeMessage(g_pars.c5g_idx,
+ nas_pdu, /* Registration request */
+ f_ULI(),
+ mo_Signalling));
+ NGAP.send(tx_pdu);
+
+ /* Expect updated KSI from network following 5G Core standards
+ *(open5gs.git 70310979c58fe186e9eaa06bec9d9a31f24ff7a1): */
+ if (g_pars.kset_id.nasKeySetId != tsc_NasKsi_NoKey) {
+ if (g_pars.kset_id.nasKeySetId == '110'B) {
+ g_pars.kset_id.nasKeySetId := '000'B;
+ } else {
+ g_pars.kset_id.nasKeySetId := int2bit(bit2int(g_pars.kset_id.nasKeySetId) + 1, 3);
+ }
+ }
+
+ as_ngap_handle_auth();
+ as_ngap_handle_sec_mode();
+
+ NGAP.receive(cr_NG_REGISTRATION_ACCEPT) -> value rx_nas;
+ NGAP.send(cs_NG_REGISTRATION_COMPLETE);
+
+ as_ngap_handle_configuration_update();
+
+ f_pdu_sess_establish();
+}
+
+}

To view, visit change 40752. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: If7edf8ee63c71fbf949e2d340cf3881fd8e3ba41
Gerrit-Change-Number: 40752
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>