pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/40752?usp=email )
Change subject: Move ConnHdlr logic to its own file
......................................................................
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(a)sysmocom.de>
+ * All rights reserved.
+ * Author: Pau Espin Pedrol <pespin(a)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
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/40752?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
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(a)sysmocom.de>