diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn index dadd5bfa9..69e187c7f 100644 --- a/bsc/BSC_Tests.ttcn +++ b/bsc/BSC_Tests.ttcn @@ -1673,10 +1673,12 @@ function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2. var template BSSMAP_IE_KC128 kc128 := omit; if (ispresent(enc)) { var TestHdlrEncrParams v_enc := valueof(enc); - encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg)); - chosenEncryptionAlgorithm := valueof( - ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int( - f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg)), 1))); + encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted)); + if (ispresent(v_enc.enc_alg_chosen)) { + chosenEncryptionAlgorithm := valueof( + ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int( + f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1))); + } if (ispresent(v_enc.enc_kc128)) { kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128); } @@ -3781,8 +3783,7 @@ testcase TC_ciph_mode_a5_2_0() runs on test_CT { var MSC_ConnHdlr vc_conn; var TestHdlrParams pars := f_gen_test_hdlr_pars(); - pars.encr := valueof(t_EncrParams('05'O, f_rnd_octstring(8))); /* A5/0 and A5/2 (0x01|0x04)*/ - pars.encr_exp_enc_alg := '04'O; /* A5/2 */ + pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/ f_init(1, true); f_vty_encryption_a5("0 1 2 3"); @@ -3797,8 +3798,7 @@ testcase TC_ciph_mode_a5_2_1() runs on test_CT { var MSC_ConnHdlr vc_conn; var TestHdlrParams pars := f_gen_test_hdlr_pars(); - pars.encr := valueof(t_EncrParams('06'O, f_rnd_octstring(8))); /* A5/1 and A5/2 (0x02|0x04)*/ - pars.encr_exp_enc_alg := '02'O; /* A5/1 */ + pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/ f_init(1, true); f_vty_encryption_a5("1 2"); @@ -6108,27 +6108,27 @@ testcase TC_ho_into_this_bsc() runs on test_CT { f_shutdown_helper(); } -function f_tc_ho_into_this_bsc_a5(OCT1 encr_alg) runs on test_CT { +function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr) runs on test_CT { var TestHdlrParams pars := f_gen_test_hdlr_pars(); - pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16))); + pars.encr := encr; f_tc_ho_into_this_bsc_main(pars); f_shutdown_helper(); } testcase TC_ho_into_this_bsc_a5_0() runs on test_CT { - f_tc_ho_into_this_bsc_a5('01'O); + f_tc_ho_into_this_bsc_a5(f_encr_params('01'O)); } testcase TC_ho_into_this_bsc_a5_1() runs on test_CT { - f_tc_ho_into_this_bsc_a5('02'O); + f_tc_ho_into_this_bsc_a5(f_encr_params('02'O)); } testcase TC_ho_into_this_bsc_a5_3() runs on test_CT { - f_tc_ho_into_this_bsc_a5('08'O); + f_tc_ho_into_this_bsc_a5(f_encr_params('08'O)); } testcase TC_ho_into_this_bsc_a5_4() runs on test_CT { - f_tc_ho_into_this_bsc_a5('10'O); + f_tc_ho_into_this_bsc_a5(f_encr_params('10'O)); } testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT { diff --git a/bsc/MSC_ConnectionHandler.ttcn b/bsc/MSC_ConnectionHandler.ttcn index 109194b1f..c2b49c873 100644 --- a/bsc/MSC_ConnectionHandler.ttcn +++ b/bsc/MSC_ConnectionHandler.ttcn @@ -550,17 +550,85 @@ function f_create_bssmap_exp(octetstring l3_enc) runs on MSC_ConnHdlr { } type record TestHdlrEncrParams { - OCT1 enc_alg, + /* A mask of multiple encryption algorithms, for Encryption Information IE. */ + OCT1 enc_alg_permitted, + /* Expect this encryption algorithm in Channel Activation from the BSC. + * To expect no encryption, set to '01'O == A5/0. */ + OCT1 enc_alg_expect, + /* In BSSMAP, the Chosen Encryption Algorithm IE that the test sends to the BSC. + * When set to omit, the MSC will not send a Chosen Encryption Algorithm IE. */ + OCT1 enc_alg_chosen optional, octetstring enc_key, octetstring enc_kc128 optional }; -template (value) TestHdlrEncrParams t_EncrParams(OCT1 alg, octetstring key, template (omit) octetstring kc128 := omit) := { - enc_alg := alg, +template (value) TestHdlrEncrParams t_EncrParams(OCT1 alg_permitted, + octetstring key, template (omit) octetstring kc128 := omit) := { + enc_alg_permitted := alg_permitted, + enc_alg_expect := alg_permitted, /* <- for compat with tests before enc_alg_expect was added */ + enc_alg_chosen := alg_permitted, /* <- for compat with tests before enc_alg_chosen was added */ enc_key := key, enc_kc128 := kc128 } +template (value) TestHdlrEncrParams t_EncrParams2(OCT1 alg_permitted, + OCT1 alg_expect, + template(omit) OCT1 alg_chosen, + octetstring key, + template (omit) octetstring kc128 := omit) := { + enc_alg_permitted := alg_permitted, + enc_alg_expect := alg_expect, + enc_alg_chosen := alg_chosen, + enc_key := key, + enc_kc128 := kc128 +} + +/* Convenience for common t_EncrParams2 usage. + * + * To test a scenario where only A5/3 is permitted: + * f_encr_params('08'O); + * To test a scenario where A5/3 is chosen from A5/0,A5/1,A5/3 (1 | 2 | 8 = 11 = 0xb): + * f_encr_params('0b'O, '08'O); + * To test the same, but the Chosen Encryption Algorithm IE should reflect A5/1: + * f_encr_params('0b'O, '08'O, '02'O); + * To test the same, but the MSC sends no Chosen Encryption Algorithm IE: + * f_encr_params('0b'O, '08'O, omit); + * + * Set alg_chosen and alg_expect magically when == '00'O: + * - enc_alg_expect is set to alg_chosen if present, else to alg_permitted. + * - enc_alg_chosen is set to alg_permitted. + * When only alg_permitted is given, alg_permitted must reflect only one algorithm, or f_cipher_mode_bssmap_to_rsl() + * will fail. + * When alg_chosen is passed as omit, the messages from the MSC will not contain a Chosen Encryption Algorithm IE. + */ +function f_encr_params(OCT1 alg_permitted, OCT1 alg_expect := '00'O, template (omit) OCT1 alg_chosen := '00'O, + boolean kc128 := false) + return TestHdlrEncrParams +{ + if (not istemplatekind(alg_chosen, "omit")) { + if (valueof(alg_chosen) == '00'O) { + if (alg_expect != '00'O) { + alg_chosen := alg_expect; + } else { + /* In this case, alg_permitted should have only one permitted algo */ + alg_chosen := alg_permitted; + } + } + if (alg_expect == '00'O) { + alg_expect := valueof(alg_chosen); + } + } + if (alg_expect == '00'O) { + /* In this case, alg_permitted should have only one permitted algo */ + alg_expect := valueof(alg_permitted); + } + var template octetstring kc := omit; + if (kc128) { + kc := f_rnd_octstring(16); + } + return valueof(t_EncrParams2(alg_permitted, alg_expect, alg_chosen, f_rnd_octstring(8), kc)); +} + type record TestHdlrParamsLcls { GlobalCallReferenceValue gcr optional, /* LCLS Configuration */ @@ -588,7 +656,6 @@ type record TestHdlrParams { RSL_IE_Body expect_mr_conf_ie optional, /* typically present for AMR codecs */ bitstring expect_mr_s0_s7 optional, /* typically present for AMR codecs */ TestHdlrEncrParams encr optional, - OCT1 encr_exp_enc_alg optional, /* if set, expect a different enc_alg than encr.enc_alg */ TestHdlrParamsLcls lcls, SCCP_PAR_Address sccp_addr_msc optional, SCCP_PAR_Address sccp_addr_bsc optional, @@ -618,7 +685,6 @@ template (value) TestHdlrParams t_def_TestHdlrPars := { expect_mr_conf_ie := omit, expect_mr_s0_s7 := omit, encr := omit, - encr_exp_enc_alg := omit, lcls := { gcr := omit, cfg := omit, @@ -740,24 +806,12 @@ function f_cipher_mode_bssmap_to_rsl(OCT1 alg_bssmap) return RSL_AlgId else if (alg_bssmap == '80'O) { return RSL_ALG_ID_A5_7; } else { - Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected Encryption Algorithm"); + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected Encryption Algorithm: " & + oct2str(alg_bssmap)); return RSL_ALG_ID_A5_0; } } -function f_cipher_mode_bssmap_to_rsl_exp_enc_alg() runs on MSC_ConnHdlr return RSL_AlgId -{ - var OCT1 enc_alg; - - if (ispresent(g_pars.encr_exp_enc_alg)) { - enc_alg := g_pars.encr_exp_enc_alg; - } else { - enc_alg := g_pars.encr.enc_alg; - } - - return f_cipher_mode_bssmap_to_rsl(enc_alg); -} - function f_verify_encr_info(RSL_Message rsl) runs on MSC_ConnHdlr { var RSL_IE_Body encr_info; var RSL_AlgId alg_rsl; @@ -776,7 +830,7 @@ function f_verify_encr_info(RSL_Message rsl) runs on MSC_ConnHdlr { /* RSL uses a different representation of the encryption algorithm, * so we need to convert first */ - alg_rsl := f_cipher_mode_bssmap_to_rsl_exp_enc_alg(); + alg_rsl := f_cipher_mode_bssmap_to_rsl(g_pars.encr.enc_alg_expect); if (alg_rsl == RSL_ALG_ID_A5_4 and ispresent(g_pars.encr.enc_kc128)) { expect_kc := g_pars.encr.enc_kc128; @@ -820,9 +874,9 @@ runs on MSC_ConnHdlr { var RSL_Message rsl; if (isvalue(enc.enc_kc128)) { - BSSAP.send(ts_BSSMAP_CipherModeCmdKc128(enc.enc_alg, enc.enc_key, valueof(enc.enc_kc128))); + BSSAP.send(ts_BSSMAP_CipherModeCmdKc128(enc.enc_alg_permitted, enc.enc_key, valueof(enc.enc_kc128))); } else { - BSSAP.send(ts_BSSMAP_CipherModeCmd(enc.enc_alg, enc.enc_key)); + BSSAP.send(ts_BSSMAP_CipherModeCmd(enc.enc_alg_permitted, enc.enc_key)); } alt { @@ -843,7 +897,7 @@ runs on MSC_ConnHdlr { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected Cipher Mode Complete"); } else { setverdict(pass); - var RSL_AlgId alg_rsl := f_cipher_mode_bssmap_to_rsl_exp_enc_alg(); + var RSL_AlgId alg_rsl := f_cipher_mode_bssmap_to_rsl(g_pars.encr.enc_alg_expect); if (oct2int(bssap.pdu.bssmap.cipherModeComplete.chosenEncryptionAlgorithm.algorithmIdentifier) != enum2int(alg_rsl)) { setverdict(fail, "Unexpected Encryption Algorithm ID in BSSMAP Cipher Mode Complete"); } @@ -941,11 +995,11 @@ private function f_check_chan_act(AssignmentState st, RSL_Message chan_act) runs var RSL_IE_Body ms_power_param; var RSL_IE_Body ms_power; - if (ispresent(g_pars.encr) and g_pars.encr.enc_alg != '01'O) { + if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_permitted != '01'O) { if (not f_rsl_find_ie(chan_act, RSL_IE_ENCR_INFO, encr_info)) { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Missing Encryption IE in CHAN ACT"); } else { - var RSL_AlgId alg := f_cipher_mode_bssmap_to_rsl_exp_enc_alg(); + var RSL_AlgId alg := f_cipher_mode_bssmap_to_rsl(g_pars.encr.enc_alg_expect); var octetstring expect_key; if (alg == RSL_ALG_ID_A5_4) { expect_key := g_pars.encr.enc_kc128;