Loading captures/TC_NGAP_GNB_PDU_01.pcap +33.6 KiB (35.6 KiB) File changed.No diff preview for this file type. View original file View changed file ccsrc/Externals/ia2_128.cc +21 −11 Changes for ccsrc/Externals/ia2_128.cc: 21 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -32,18 +32,19 @@ int ia2_128::encrypt(const uint8_t algo_id, unsigned char** cyphered, uint32_t* cyphered_length) { loggers::get_instance().log(">>> ia2_128::encrypt: Starting encryption"); loggers::get_instance().log_to_hexa(">>> ia2_128::encrypt: knas_enc", knas_enc, 16); loggers::get_instance().log_to_hexa(">>> ia2_128::encrypt: payload", payload, payload_length); loggers::get_instance().log(">>> ia2_128::encrypt: algo_id: %d", algo_id); loggers::get_instance().log(">>> ia2_128::encrypt: count: %u", count); loggers::get_instance().log(">>> ia2_128::encrypt: bearer: %d", bearer); loggers::get_instance().log(">>> ia2_128::encrypt: direction: %d", direction); loggers::get_instance().log(">>> ia2_128::encrypt: payload_length: %u", payload_length); // Input validation // Input validation (must run before the hex-dump logging below, which dereferences these pointers) if (!knas_enc || !payload || !cyphered || !cyphered_length) { loggers::get_instance().error("ia2_128::encrypt: Wrong input parameters"); return -1; } loggers::get_instance().log_to_hexa(">>> ia2_128::encrypt: knas_enc", knas_enc, 16); loggers::get_instance().log_to_hexa(">>> ia2_128::encrypt: payload", payload, payload_length); if (payload_length == 0) { loggers::get_instance().error("ia2_128::encrypt: Wrong payload length"); Loading Loading @@ -124,18 +125,19 @@ int ia2_128::decrypt(const uint8_t algo_id, unsigned char** payload, uint32_t* payload_length) { loggers::get_instance().log(">>> ia2_128::decrypt: Starting decryption"); loggers::get_instance().log_to_hexa(">>> ia2_128::decrypt: knas_enc", knas_enc, 16); loggers::get_instance().log_to_hexa(">>> ia2_128::decrypt: cyphered", cyphered, cyphered_length); loggers::get_instance().log(">>> ia2_128::decrypt: algo_id: %d", algo_id); loggers::get_instance().log(">>> ia2_128::decrypt: count: %u", count); loggers::get_instance().log(">>> ia2_128::decrypt: bearer: %d", bearer); loggers::get_instance().log(">>> ia2_128::decrypt: direction: %d", direction); loggers::get_instance().log(">>> ia2_128::decrypt: cyphered_length: %u", cyphered_length); // Input validation // Input validation (must run before the hex-dump logging below, which dereferences these pointers) if (!knas_enc || !cyphered || !payload || !payload_length) { loggers::get_instance().error("ia2_128::decrypt: Wrong input parameters"); return -1; } loggers::get_instance().log_to_hexa(">>> ia2_128::decrypt: knas_enc", knas_enc, 16); loggers::get_instance().log_to_hexa(">>> ia2_128::decrypt: cyphered", cyphered, cyphered_length); if (cyphered_length == 0) { loggers::get_instance().error("ia2_128::encrypt: Wrong cyphered length"); Loading Loading @@ -215,19 +217,19 @@ int ia2_128::mac(const uint8_t algo_id, const uint32_t payload_length, unsigned char** mac, uint32_t* mac_length) { loggers::get_instance().log_to_hexa(">>> ia2_128::mac: knas_int", knas_int, KEY_SIZE); loggers::get_instance().log(">>> ia2_128::mac: payload_length: %d", payload_length); loggers::get_instance().log_to_hexa(">>> ia2_128::mac: payload", payload, payload_length); loggers::get_instance().log(">>> ia2_128::mac: algo_id: %d", algo_id); loggers::get_instance().log(">>> ia2_128::mac: count: %u", count); loggers::get_instance().log(">>> ia2_128::mac: bearer: %d", bearer); loggers::get_instance().log(">>> ia2_128::mac: direction: %d", direction); // Input validation // Input validation (must run before the hex-dump logging below, which dereferences these pointers) if (!knas_int || !payload || !mac || !mac_length) { loggers::get_instance().error("ia2_128::mac: Wrong input parameters"); return -1; } loggers::get_instance().log_to_hexa(">>> ia2_128::mac: knas_int", knas_int, KEY_SIZE); loggers::get_instance().log_to_hexa(">>> ia2_128::mac: payload", payload, payload_length); if (payload_length == 0) { loggers::get_instance().error("ia2_128::mac: Wrong payload length"); Loading Loading @@ -295,6 +297,7 @@ int ia2_128::mac(const uint8_t algo_id, // Truncate CMAC output to 4 bytes (take the first 4 bytes) std::memcpy(*mac, cmac_output, MAC_SIZE); loggers::get_instance().log_to_hexa("ia2_128::mac: mac: ", *mac, *mac_length); result = 0; cleanup: #pragma GCC diagnostic push Loading @@ -302,9 +305,16 @@ int ia2_128::mac(const uint8_t algo_id, CMAC_CTX_free(ctx); #pragma GCC diagnostic pop std::free(input_block); if (result != 0) { // A CMAC_* call above failed (goto cleanup): *mac was allocated (see malloc above) // but never filled in, so it must not be handed back to the caller as a valid MAC. std::free(*mac); *mac = nullptr; *mac_length = 0; } loggers::get_instance().log("<<< ia2_128::mac: result: 0"); return 0; loggers::get_instance().log("<<< ia2_128::mac: result: %d", result); return result; } // ETSI TS 133 401 V18.3.0 (2025-04) Annex B.1.3 128-EEA2 Loading ttcn/AtsNGAP/NGAP_UtProbe.ttcn +10 −0 Changes for ttcn/AtsNGAP/NGAP_UtProbe.ttcn: 10 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ module NGAP_UtProbe { import from UpperTesterPtcToMtcDefs all; import from UpperTesterFunctions all; import from NGAP_UtDispatcher all; import from LibNGAP_Pixits all; import from Lib_NG_NAS_Security_Functions all; modulepar charstring PX_UT_PROBE_AT_CMD := "ATI<CR>"; modulepar float PX_UT_PROBE_TIMEOUT := 15.0; Loading Loading @@ -55,6 +57,14 @@ module NGAP_UtProbe { log("MODEM_RESTART: ", v_cnf); if (not v_cnf.Result) { setverdict(fail); stop; } v_cnf := fl_UT_ApplyCommandRetCnf(utPtcMtcPort, cas_UT_Req(PLMN_MANUAL, CNF_REQUIRED, cs_ManualPlmn("\"" & f_ConvertPLMNtoString(fl_NasNN_MCC2PlmnId(PX_NAS_MCC, PX_NAS_MNC)) & "\""))); log("PLMN_MANUAL: ", v_cnf); if (not v_cnf.Result) { setverdict(fail); stop; } v_cnf := fl_UT_ApplyCommandRetCnf(utPtcMtcPort, cas_UT_Req(PLMN_AUTOMATIC, CNF_REQUIRED)); log("PLMN_AUTOMATIC: ", v_cnf); if (not v_cnf.Result) { setverdict(fail); stop; } v_cnf := fl_UT_ApplyCommandRetCnf(utPtcMtcPort, cas_UT_Req(CHECK_PLMN, CNF_REQUIRED)); log("CHECK_PLMN (expected unsupported): ", v_cnf); if (v_cnf.Result) { setverdict(fail); stop; } Loading ttcn/LibNGAP/lib_system/LibNGAP_Functions.ttcn +78 −1 Changes for ttcn/LibNGAP/lib_system/LibNGAP_Functions.ttcn: 78 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -303,6 +303,80 @@ module LibNGAP_Functions { log(">>> f_await_registration_request"); // REGISTRATION_REQUEST tc_ac.start; alt { // In case the UE rejected the authentication vector with a Synch failure and returned an AUTS for resync (per TS 24.501 §5.4.1.3.7) [] N2_gNBaMF_P.check( receive( mw_ngap_initMsg( mw_n2_UplinkNASTransport( -, -, decmatch( mw_NG_AUTHENTICATION_FAILURE( mw_GMM_GSM_Cause( -, int2bit(21, 8) // SYNC failure ))))))) { // the UE rejected the authentication vector with a Synch failure f_recv_NGAP_PDU( mw_ngap_initMsg( mw_n2_UplinkNASTransport( -, -, decmatch( mw_NG_AUTHENTICATION_FAILURE( mw_GMM_GSM_Cause( -, int2bit(21, 8) // SYNC failure )))))); f_NASPDU_Get(vc_recvNGAP_PDU); // Re-calculate the security context with the AUTS value received from the UE // (TS 33.102 clause 6.3.3 "Re-synchronisation procedure"): // AUTS = (SQN_MS xor AK*) (48 bits) || MAC-S (64 bits) // AK* = f5star(K, RAND) -- RAND is the one from the rejected Authentication Request // SQN_MS = (SQN_MS xor AK*) xor AK* // MAC-S = f1star(K, RAND, SQN_MS, AMF*) with a dummy AMF* of all zeros if (ispresent(vc_recvNgNasUl_Msg.authentication_Failure.authFailureParam)) { var B112_Type v_auts := vc_recvNgNasUl_Msg.authentication_Failure.authFailureParam.auts; var B48_Type v_sqn_ms_akstar := substr(v_auts, 0, 48); var B64_Type v_mac_s := substr(v_auts, 48, 64); log("f_await_registration_request: v_auts=", bit2oct(v_auts)); var B48_Type v_ak_star; if (f_f5star(PX_SUBSCRIPTION_KEY, vc_ng_nas_security_params_type.AuthParams.RandValue, v_ak_star) != 0) { log("*** " & __SCOPE__ & ": FAIL: 'f_f5star' failed to compute AK*"); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: 'f_f5star' failed to compute AK*"); } var B48_Type v_sqn_ms := v_sqn_ms_akstar xor4b v_ak_star; log("f_await_registration_request: v_sqn_ms=", bit2oct(v_sqn_ms)); // Verify MAC-S; the resynchronisation MAC always uses a dummy AMF* of all zeros // so it does not have to be sent in the clear (TS 33.102 clause 6.3.3) var B64_Type v_mac_s_expected; if (f_f1star(PX_SUBSCRIPTION_KEY, vc_ng_nas_security_params_type.AuthParams.RandValue, v_sqn_ms, int2bit(0, 16), v_mac_s_expected) != 0) { log("*** " & __SCOPE__ & ": FAIL: 'f_f1star' failed to compute MAC-S"); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: 'f_f1star' failed to compute MAC-S"); } if (PX_CHECK_SECURITY and (v_mac_s != v_mac_s_expected)) { log("*** " & __SCOPE__ & ": FAIL: MAC-S mismatch: received=", bit2oct(v_mac_s), ", expected=", bit2oct(v_mac_s_expected)); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: MAC-S mismatch in resynchronisation"); } // Advance the network's SQN past the UE's own counter so the Authentication Request // that follows (f_send_authentication_request_await_authentication_response) is accepted vc_NG_NAS_SQN := int2bit(bit2int(v_sqn_ms) + 1, 48); log("f_await_registration_request: resynchronised vc_NG_NAS_SQN=", bit2oct(vc_NG_NAS_SQN)); } else { log("*** " & __SCOPE__ & ": FAIL: Authentication failure with no AUTS"); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: Authentication failure with no AUTS"); } } [] tc_ac.timeout { // No message received, let's consider the message was accepted and proceed with the test case execution log("*** " & __SCOPE__ & ": FAIL: No NAS message received"); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: No NAS message received"); } } f_recv_NGAP_PDU( mw_ngap_initMsg( mw_n2_initialUeMessage Loading Loading @@ -621,7 +695,10 @@ module LibNGAP_Functions { f_force_opc(PX_OPERATOR_SECRET_KEY); } // Compute MAC_A var B48_Type v_sqn := PX_SQN; // Use vc_NG_NAS_SQN rather than PX_SQN directly: it starts at PX_SQN but is advanced by // f_await_registration_request whenever the UE rejects a vector with a Synch failure, // so a retried Authentication Request uses a SQN the UE will actually accept. var B48_Type v_sqn := vc_NG_NAS_SQN; var B16_Type v_amf := PX_AMF; // AMF: Authentication Management Field vc_ng_nas_security_params_type.AuthParams.RandValue := PX_RAND_VALUE; var B64_Type v_mac_a; Loading ttcn/LibNGAP/lib_system/LibNGAP_Interface.ttcn +7 −0 Changes for ttcn/LibNGAP/lib_system/LibNGAP_Interface.ttcn: 7 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ module LibNGAP_Interface { import from NGAP_PDU_Contents language "ASN.1:1997" all; import from LibNGAP_Pixits all; // Lib_NG_NAS import from Lib_NG_NAS_Pixits all; // UpperTester import from UpperTesterPtcToMtcDefs all; import from UpperTesterCommon all; Loading Loading @@ -65,6 +68,8 @@ module LibNGAP_Interface { var NG_NAS_UL_Message_Type vc_recvNgNasUl_Msg; var NG_NAS_DL_Message_Type vc_recvNgNasDl_Msg; var NG_NAS_SecurityParams_Type vc_ng_nas_security_params_type := {}; var B48_Type vc_NG_NAS_SQN := PX_SQN; // Network's current SQN for 5G-AKA vector generation (TS 33.102 clause 6.3.3); // advanced by f_await_registration_request after a Synch failure/AUTS from the UE var boolean vc_serverStop:=false; // test adapter params Loading Loading @@ -99,6 +104,8 @@ module LibNGAP_Interface { timer tc_wait := PX_NGAP_TWAIT; timer tc_noac := PX_TNOAC; timer tc_delay := 0.3; // delay next Request timer tc_ac := PX_NGAP_TWAIT; // used by f_await_registration_request to bound the wait for either // an Authentication Failure (Synch failure) or the Registration Request // FSCOM: TTCN-3 timer are in seconds (ETSI ES 201 873-1 V4.16.1 (2024-10) Clause 12 Declaring timers) // Variables for storing default references Loading Loading
captures/TC_NGAP_GNB_PDU_01.pcap +33.6 KiB (35.6 KiB) File changed.No diff preview for this file type. View original file View changed file
ccsrc/Externals/ia2_128.cc +21 −11 Changes for ccsrc/Externals/ia2_128.cc: 21 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -32,18 +32,19 @@ int ia2_128::encrypt(const uint8_t algo_id, unsigned char** cyphered, uint32_t* cyphered_length) { loggers::get_instance().log(">>> ia2_128::encrypt: Starting encryption"); loggers::get_instance().log_to_hexa(">>> ia2_128::encrypt: knas_enc", knas_enc, 16); loggers::get_instance().log_to_hexa(">>> ia2_128::encrypt: payload", payload, payload_length); loggers::get_instance().log(">>> ia2_128::encrypt: algo_id: %d", algo_id); loggers::get_instance().log(">>> ia2_128::encrypt: count: %u", count); loggers::get_instance().log(">>> ia2_128::encrypt: bearer: %d", bearer); loggers::get_instance().log(">>> ia2_128::encrypt: direction: %d", direction); loggers::get_instance().log(">>> ia2_128::encrypt: payload_length: %u", payload_length); // Input validation // Input validation (must run before the hex-dump logging below, which dereferences these pointers) if (!knas_enc || !payload || !cyphered || !cyphered_length) { loggers::get_instance().error("ia2_128::encrypt: Wrong input parameters"); return -1; } loggers::get_instance().log_to_hexa(">>> ia2_128::encrypt: knas_enc", knas_enc, 16); loggers::get_instance().log_to_hexa(">>> ia2_128::encrypt: payload", payload, payload_length); if (payload_length == 0) { loggers::get_instance().error("ia2_128::encrypt: Wrong payload length"); Loading Loading @@ -124,18 +125,19 @@ int ia2_128::decrypt(const uint8_t algo_id, unsigned char** payload, uint32_t* payload_length) { loggers::get_instance().log(">>> ia2_128::decrypt: Starting decryption"); loggers::get_instance().log_to_hexa(">>> ia2_128::decrypt: knas_enc", knas_enc, 16); loggers::get_instance().log_to_hexa(">>> ia2_128::decrypt: cyphered", cyphered, cyphered_length); loggers::get_instance().log(">>> ia2_128::decrypt: algo_id: %d", algo_id); loggers::get_instance().log(">>> ia2_128::decrypt: count: %u", count); loggers::get_instance().log(">>> ia2_128::decrypt: bearer: %d", bearer); loggers::get_instance().log(">>> ia2_128::decrypt: direction: %d", direction); loggers::get_instance().log(">>> ia2_128::decrypt: cyphered_length: %u", cyphered_length); // Input validation // Input validation (must run before the hex-dump logging below, which dereferences these pointers) if (!knas_enc || !cyphered || !payload || !payload_length) { loggers::get_instance().error("ia2_128::decrypt: Wrong input parameters"); return -1; } loggers::get_instance().log_to_hexa(">>> ia2_128::decrypt: knas_enc", knas_enc, 16); loggers::get_instance().log_to_hexa(">>> ia2_128::decrypt: cyphered", cyphered, cyphered_length); if (cyphered_length == 0) { loggers::get_instance().error("ia2_128::encrypt: Wrong cyphered length"); Loading Loading @@ -215,19 +217,19 @@ int ia2_128::mac(const uint8_t algo_id, const uint32_t payload_length, unsigned char** mac, uint32_t* mac_length) { loggers::get_instance().log_to_hexa(">>> ia2_128::mac: knas_int", knas_int, KEY_SIZE); loggers::get_instance().log(">>> ia2_128::mac: payload_length: %d", payload_length); loggers::get_instance().log_to_hexa(">>> ia2_128::mac: payload", payload, payload_length); loggers::get_instance().log(">>> ia2_128::mac: algo_id: %d", algo_id); loggers::get_instance().log(">>> ia2_128::mac: count: %u", count); loggers::get_instance().log(">>> ia2_128::mac: bearer: %d", bearer); loggers::get_instance().log(">>> ia2_128::mac: direction: %d", direction); // Input validation // Input validation (must run before the hex-dump logging below, which dereferences these pointers) if (!knas_int || !payload || !mac || !mac_length) { loggers::get_instance().error("ia2_128::mac: Wrong input parameters"); return -1; } loggers::get_instance().log_to_hexa(">>> ia2_128::mac: knas_int", knas_int, KEY_SIZE); loggers::get_instance().log_to_hexa(">>> ia2_128::mac: payload", payload, payload_length); if (payload_length == 0) { loggers::get_instance().error("ia2_128::mac: Wrong payload length"); Loading Loading @@ -295,6 +297,7 @@ int ia2_128::mac(const uint8_t algo_id, // Truncate CMAC output to 4 bytes (take the first 4 bytes) std::memcpy(*mac, cmac_output, MAC_SIZE); loggers::get_instance().log_to_hexa("ia2_128::mac: mac: ", *mac, *mac_length); result = 0; cleanup: #pragma GCC diagnostic push Loading @@ -302,9 +305,16 @@ int ia2_128::mac(const uint8_t algo_id, CMAC_CTX_free(ctx); #pragma GCC diagnostic pop std::free(input_block); if (result != 0) { // A CMAC_* call above failed (goto cleanup): *mac was allocated (see malloc above) // but never filled in, so it must not be handed back to the caller as a valid MAC. std::free(*mac); *mac = nullptr; *mac_length = 0; } loggers::get_instance().log("<<< ia2_128::mac: result: 0"); return 0; loggers::get_instance().log("<<< ia2_128::mac: result: %d", result); return result; } // ETSI TS 133 401 V18.3.0 (2025-04) Annex B.1.3 128-EEA2 Loading
ttcn/AtsNGAP/NGAP_UtProbe.ttcn +10 −0 Changes for ttcn/AtsNGAP/NGAP_UtProbe.ttcn: 10 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ module NGAP_UtProbe { import from UpperTesterPtcToMtcDefs all; import from UpperTesterFunctions all; import from NGAP_UtDispatcher all; import from LibNGAP_Pixits all; import from Lib_NG_NAS_Security_Functions all; modulepar charstring PX_UT_PROBE_AT_CMD := "ATI<CR>"; modulepar float PX_UT_PROBE_TIMEOUT := 15.0; Loading Loading @@ -55,6 +57,14 @@ module NGAP_UtProbe { log("MODEM_RESTART: ", v_cnf); if (not v_cnf.Result) { setverdict(fail); stop; } v_cnf := fl_UT_ApplyCommandRetCnf(utPtcMtcPort, cas_UT_Req(PLMN_MANUAL, CNF_REQUIRED, cs_ManualPlmn("\"" & f_ConvertPLMNtoString(fl_NasNN_MCC2PlmnId(PX_NAS_MCC, PX_NAS_MNC)) & "\""))); log("PLMN_MANUAL: ", v_cnf); if (not v_cnf.Result) { setverdict(fail); stop; } v_cnf := fl_UT_ApplyCommandRetCnf(utPtcMtcPort, cas_UT_Req(PLMN_AUTOMATIC, CNF_REQUIRED)); log("PLMN_AUTOMATIC: ", v_cnf); if (not v_cnf.Result) { setverdict(fail); stop; } v_cnf := fl_UT_ApplyCommandRetCnf(utPtcMtcPort, cas_UT_Req(CHECK_PLMN, CNF_REQUIRED)); log("CHECK_PLMN (expected unsupported): ", v_cnf); if (v_cnf.Result) { setverdict(fail); stop; } Loading
ttcn/LibNGAP/lib_system/LibNGAP_Functions.ttcn +78 −1 Changes for ttcn/LibNGAP/lib_system/LibNGAP_Functions.ttcn: 78 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -303,6 +303,80 @@ module LibNGAP_Functions { log(">>> f_await_registration_request"); // REGISTRATION_REQUEST tc_ac.start; alt { // In case the UE rejected the authentication vector with a Synch failure and returned an AUTS for resync (per TS 24.501 §5.4.1.3.7) [] N2_gNBaMF_P.check( receive( mw_ngap_initMsg( mw_n2_UplinkNASTransport( -, -, decmatch( mw_NG_AUTHENTICATION_FAILURE( mw_GMM_GSM_Cause( -, int2bit(21, 8) // SYNC failure ))))))) { // the UE rejected the authentication vector with a Synch failure f_recv_NGAP_PDU( mw_ngap_initMsg( mw_n2_UplinkNASTransport( -, -, decmatch( mw_NG_AUTHENTICATION_FAILURE( mw_GMM_GSM_Cause( -, int2bit(21, 8) // SYNC failure )))))); f_NASPDU_Get(vc_recvNGAP_PDU); // Re-calculate the security context with the AUTS value received from the UE // (TS 33.102 clause 6.3.3 "Re-synchronisation procedure"): // AUTS = (SQN_MS xor AK*) (48 bits) || MAC-S (64 bits) // AK* = f5star(K, RAND) -- RAND is the one from the rejected Authentication Request // SQN_MS = (SQN_MS xor AK*) xor AK* // MAC-S = f1star(K, RAND, SQN_MS, AMF*) with a dummy AMF* of all zeros if (ispresent(vc_recvNgNasUl_Msg.authentication_Failure.authFailureParam)) { var B112_Type v_auts := vc_recvNgNasUl_Msg.authentication_Failure.authFailureParam.auts; var B48_Type v_sqn_ms_akstar := substr(v_auts, 0, 48); var B64_Type v_mac_s := substr(v_auts, 48, 64); log("f_await_registration_request: v_auts=", bit2oct(v_auts)); var B48_Type v_ak_star; if (f_f5star(PX_SUBSCRIPTION_KEY, vc_ng_nas_security_params_type.AuthParams.RandValue, v_ak_star) != 0) { log("*** " & __SCOPE__ & ": FAIL: 'f_f5star' failed to compute AK*"); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: 'f_f5star' failed to compute AK*"); } var B48_Type v_sqn_ms := v_sqn_ms_akstar xor4b v_ak_star; log("f_await_registration_request: v_sqn_ms=", bit2oct(v_sqn_ms)); // Verify MAC-S; the resynchronisation MAC always uses a dummy AMF* of all zeros // so it does not have to be sent in the clear (TS 33.102 clause 6.3.3) var B64_Type v_mac_s_expected; if (f_f1star(PX_SUBSCRIPTION_KEY, vc_ng_nas_security_params_type.AuthParams.RandValue, v_sqn_ms, int2bit(0, 16), v_mac_s_expected) != 0) { log("*** " & __SCOPE__ & ": FAIL: 'f_f1star' failed to compute MAC-S"); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: 'f_f1star' failed to compute MAC-S"); } if (PX_CHECK_SECURITY and (v_mac_s != v_mac_s_expected)) { log("*** " & __SCOPE__ & ": FAIL: MAC-S mismatch: received=", bit2oct(v_mac_s), ", expected=", bit2oct(v_mac_s_expected)); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: MAC-S mismatch in resynchronisation"); } // Advance the network's SQN past the UE's own counter so the Authentication Request // that follows (f_send_authentication_request_await_authentication_response) is accepted vc_NG_NAS_SQN := int2bit(bit2int(v_sqn_ms) + 1, 48); log("f_await_registration_request: resynchronised vc_NG_NAS_SQN=", bit2oct(vc_NG_NAS_SQN)); } else { log("*** " & __SCOPE__ & ": FAIL: Authentication failure with no AUTS"); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: Authentication failure with no AUTS"); } } [] tc_ac.timeout { // No message received, let's consider the message was accepted and proceed with the test case execution log("*** " & __SCOPE__ & ": FAIL: No NAS message received"); setverdict(fail, "*** " & __SCOPE__ & ": FAIL: No NAS message received"); } } f_recv_NGAP_PDU( mw_ngap_initMsg( mw_n2_initialUeMessage Loading Loading @@ -621,7 +695,10 @@ module LibNGAP_Functions { f_force_opc(PX_OPERATOR_SECRET_KEY); } // Compute MAC_A var B48_Type v_sqn := PX_SQN; // Use vc_NG_NAS_SQN rather than PX_SQN directly: it starts at PX_SQN but is advanced by // f_await_registration_request whenever the UE rejects a vector with a Synch failure, // so a retried Authentication Request uses a SQN the UE will actually accept. var B48_Type v_sqn := vc_NG_NAS_SQN; var B16_Type v_amf := PX_AMF; // AMF: Authentication Management Field vc_ng_nas_security_params_type.AuthParams.RandValue := PX_RAND_VALUE; var B64_Type v_mac_a; Loading
ttcn/LibNGAP/lib_system/LibNGAP_Interface.ttcn +7 −0 Changes for ttcn/LibNGAP/lib_system/LibNGAP_Interface.ttcn: 7 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ module LibNGAP_Interface { import from NGAP_PDU_Contents language "ASN.1:1997" all; import from LibNGAP_Pixits all; // Lib_NG_NAS import from Lib_NG_NAS_Pixits all; // UpperTester import from UpperTesterPtcToMtcDefs all; import from UpperTesterCommon all; Loading Loading @@ -65,6 +68,8 @@ module LibNGAP_Interface { var NG_NAS_UL_Message_Type vc_recvNgNasUl_Msg; var NG_NAS_DL_Message_Type vc_recvNgNasDl_Msg; var NG_NAS_SecurityParams_Type vc_ng_nas_security_params_type := {}; var B48_Type vc_NG_NAS_SQN := PX_SQN; // Network's current SQN for 5G-AKA vector generation (TS 33.102 clause 6.3.3); // advanced by f_await_registration_request after a Synch failure/AUTS from the UE var boolean vc_serverStop:=false; // test adapter params Loading Loading @@ -99,6 +104,8 @@ module LibNGAP_Interface { timer tc_wait := PX_NGAP_TWAIT; timer tc_noac := PX_TNOAC; timer tc_delay := 0.3; // delay next Request timer tc_ac := PX_NGAP_TWAIT; // used by f_await_registration_request to bound the wait for either // an Authentication Failure (Synch failure) or the Registration Request // FSCOM: TTCN-3 timer are in seconds (ETSI ES 201 873-1 V4.16.1 (2024-10) Clause 12 Declaring timers) // Variables for storing default references Loading