msc: Cipher mode negotiation test
This adds a series of test cases that test various combinations of A5/0, A5/1, A5/2 and A5/3 on both phone as well as network config side. Change-Id: I552fa4a23b7b65613a69b1a822e28e7dea401102
This commit is contained in:
parent
de37149345
commit
9de8479399
|
@ -55,12 +55,58 @@ type record BSC_ConnHdlrPars {
|
|||
hexstring imsi,
|
||||
hexstring msisdn,
|
||||
OCT4 tmsi optional,
|
||||
MobileStationClassmark1_V cm1,
|
||||
BSSMAP_IE_ClassmarkInformationType2 cm2,
|
||||
BSSMAP_IE_ClassmarkInformationType3 cm3 optional,
|
||||
AuthVector vec optional,
|
||||
BSC_ConnHdlrNetworkPars net
|
||||
};
|
||||
|
||||
/* get a one-octet bitmaks of supported algorithms based on Classmark information */
|
||||
function f_alg_mask_from_cm(BSSMAP_IE_ClassmarkInformationType2 cm2) return OCT1 {
|
||||
var BIT8 res := '00000001'B; /* A5/0 always supported */
|
||||
|
||||
if (cm2.a5_1 == '0'B) {
|
||||
res := res or4b '00000010'B;
|
||||
}
|
||||
if (cm2.classmarkInformationType2_oct5.a5_2 == '1'B ) {
|
||||
res := res or4b '00000100'B;
|
||||
}
|
||||
if (cm2.classmarkInformationType2_oct5.a5_3 == '1'B) {
|
||||
res := res or4b '00001000'B;
|
||||
}
|
||||
/* TODO: CM3 for A5/4 and beyond */
|
||||
return bit2oct(res);
|
||||
}
|
||||
|
||||
/* determine the best algorithm available within the bit-mask */
|
||||
function f_best_alg_from_mask(OCT1 alg_in) return OCT1 {
|
||||
var BIT8 alg := oct2bit(alg_in);
|
||||
var BIT8 ordered_algs[8] := {
|
||||
'10000000'B, '01000000'B, '00100000'B, '00010000'B,
|
||||
'00001000'B, /* A5/3 */
|
||||
'00000010'B, /* A5/1 */
|
||||
'00000100'B, /* A5/2 */
|
||||
'00000001'B /* A5/0 */ }
|
||||
for (var integer i := 0; i < sizeof(ordered_algs); i := i+1) {
|
||||
if (alg and4b ordered_algs[i] != '00000000'B) {
|
||||
return bit2oct(ordered_algs[i]);
|
||||
}
|
||||
}
|
||||
return '00'O;
|
||||
}
|
||||
|
||||
/* return an integer like '1' for A5/1 based on a mask (with only one bit set */
|
||||
function f_alg_from_mask(OCT1 mask_in) return integer {
|
||||
var BIT8 mask := oct2bit(mask_in);
|
||||
for (var integer i := 0; i < 8; i := i+1) {
|
||||
if (mask and4b ('00000001'B << i) != '00000000'B) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* altstep for the global guard timer */
|
||||
private altstep as_Tguard() runs on BSC_ConnHdlr {
|
||||
[] g_Tguard.timeout {
|
||||
|
@ -172,26 +218,26 @@ runs on BSC_ConnHdlr {
|
|||
|
||||
|
||||
/* build a PDU_ML3_MS_NW containing a Location Update by IMSI */
|
||||
function f_build_lu_imsi(hexstring imsi) return PDU_ML3_MS_NW
|
||||
function f_build_lu_imsi(hexstring imsi) runs on BSC_ConnHdlr return PDU_ML3_MS_NW
|
||||
{
|
||||
var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(imsi));
|
||||
return f_build_lu(mi);
|
||||
}
|
||||
function f_build_lu_imei(hexstring imei) return PDU_ML3_MS_NW
|
||||
function f_build_lu_imei(hexstring imei) runs on BSC_ConnHdlr return PDU_ML3_MS_NW
|
||||
{
|
||||
var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(imei));
|
||||
return f_build_lu(mi);
|
||||
}
|
||||
function f_build_lu_tmsi(OCT4 tmsi) return PDU_ML3_MS_NW
|
||||
function f_build_lu_tmsi(OCT4 tmsi) runs on BSC_ConnHdlr return PDU_ML3_MS_NW
|
||||
{
|
||||
var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV(tmsi));
|
||||
return f_build_lu(mi);
|
||||
}
|
||||
private function f_build_lu(MobileIdentityLV mi) return PDU_ML3_MS_NW
|
||||
private function f_build_lu(MobileIdentityLV mi) runs on BSC_ConnHdlr return PDU_ML3_MS_NW
|
||||
{
|
||||
var LocationAreaIdentification_V old_lai := { '62F220'O, '9999'O };
|
||||
var PDU_ML3_MS_NW l3_info := valueof(ts_ML3_MO_LU_Req(valueof(ts_ML3_IE_LuType_Attach),
|
||||
old_lai, mi, valueof(ts_CM1)));
|
||||
old_lai, mi, g_pars.cm1));
|
||||
return l3_info;
|
||||
}
|
||||
|
||||
|
@ -213,7 +259,7 @@ function f_gen_auth_vec_2g() return AuthVector {
|
|||
}
|
||||
|
||||
|
||||
function f_mm_common() runs on BSC_ConnHdlr
|
||||
function f_mm_auth() runs on BSC_ConnHdlr
|
||||
{
|
||||
if (g_pars.net.expect_auth) {
|
||||
g_pars.vec := f_gen_auth_vec_2g();
|
||||
|
@ -226,10 +272,26 @@ function f_mm_common() runs on BSC_ConnHdlr
|
|||
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(g_pars.vec.rand)));
|
||||
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G(g_pars.vec.sres)));
|
||||
}
|
||||
}
|
||||
|
||||
function f_mm_common() runs on BSC_ConnHdlr
|
||||
{
|
||||
f_mm_auth();
|
||||
if (g_pars.net.expect_ciph) {
|
||||
BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc));
|
||||
BSSAP.send(ts_BSSMAP_CipherModeCompl('02'O));
|
||||
var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
|
||||
var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
|
||||
alt {
|
||||
[] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
|
||||
var OCT1 a5_chosen := f_best_alg_from_mask(a5_intersect);
|
||||
var integer a5_nr := f_alg_from_mask(a5_chosen);
|
||||
BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(a5_nr+1, 1)));
|
||||
}
|
||||
[] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
|
||||
setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
/* FIXME: Send the best available algorithm */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -368,6 +368,7 @@ function f_start_handler(void_fn fn, charstring id, integer imsi_suffix) runs on
|
|||
imsi := f_gen_imsi(imsi_suffix),
|
||||
msisdn := f_gen_msisdn(imsi_suffix),
|
||||
tmsi := omit,
|
||||
cm1 := valueof(ts_CM1),
|
||||
cm2 := valueof(ts_CM2_default),
|
||||
cm3 := omit,
|
||||
vec := omit,
|
||||
|
@ -1438,6 +1439,143 @@ testcase TC_gsup_cancel() runs on MTC_CT {
|
|||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* A5/1 only permitted on network side, and MS capable to do it */
|
||||
private function f_tc_lu_imsi_auth_tmsi_encr_1_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
|
||||
pars.net.expect_auth := true;
|
||||
pars.net.expect_ciph := true;
|
||||
pars.net.kc_support := '02'O; /* A5/1 only */
|
||||
f_init_handler(pars);
|
||||
f_perform_lu(true);
|
||||
}
|
||||
testcase TC_lu_imsi_auth_tmsi_encr_1_13() runs on MTC_CT {
|
||||
var BSC_ConnHdlr vc_conn;
|
||||
f_init();
|
||||
f_vty_config(MSCVTY, "network", "authentication required");
|
||||
f_vty_config(MSCVTY, "network", "encryption a5 1");
|
||||
|
||||
vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_1_13), testcasename(), 32);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* A5/3 only permitted on network side, and MS capable to do it */
|
||||
private function f_tc_lu_imsi_auth_tmsi_encr_3_13(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
|
||||
pars.net.expect_auth := true;
|
||||
pars.net.expect_ciph := true;
|
||||
pars.net.kc_support := '08'O; /* A5/3 only */
|
||||
f_init_handler(pars);
|
||||
f_perform_lu(true);
|
||||
}
|
||||
testcase TC_lu_imsi_auth_tmsi_encr_3_13() runs on MTC_CT {
|
||||
var BSC_ConnHdlr vc_conn;
|
||||
f_init();
|
||||
f_vty_config(MSCVTY, "network", "authentication required");
|
||||
f_vty_config(MSCVTY, "network", "encryption a5 3");
|
||||
|
||||
vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_13), testcasename(), 33);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* A5/3 only permitted on network side, and MS with only A5/1 support */
|
||||
private function f_tc_lu_imsi_auth_tmsi_encr_3_1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
|
||||
pars.net.expect_auth := true;
|
||||
pars.net.expect_ciph := true;
|
||||
pars.net.kc_support := '08'O; /* A5/3 only */
|
||||
pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
|
||||
f_init_handler(pars, 15.0);
|
||||
|
||||
/* cannot use f_perform_lu() as we expect a reject */
|
||||
var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
|
||||
f_create_gsup_expect(hex2str(g_pars.imsi));
|
||||
f_bssap_compl_l3(l3_lu);
|
||||
BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
|
||||
f_mm_auth();
|
||||
alt {
|
||||
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
|
||||
[] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
|
||||
setverdict(fail, "CipherModeCommand despite no A5 intersection");
|
||||
self.stop;
|
||||
}
|
||||
[] BSSAP.receive {
|
||||
setverdict(inconc, "Unknown/unexpected BSSAP received");
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
setverdict(pass);
|
||||
}
|
||||
testcase TC_lu_imsi_auth_tmsi_encr_3_1() runs on MTC_CT {
|
||||
var BSC_ConnHdlr vc_conn;
|
||||
f_init();
|
||||
f_vty_config(MSCVTY, "network", "authentication required");
|
||||
f_vty_config(MSCVTY, "network", "encryption a5 3");
|
||||
|
||||
vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_3_1), testcasename(), 34);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
|
||||
private function f_tc_lu_imsi_auth_tmsi_encr_13_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
|
||||
pars.net.expect_auth := true;
|
||||
pars.net.expect_ciph := true;
|
||||
pars.net.kc_support := '0A'O; /* A5/1 + A5/3 */
|
||||
pars.cm1.a5_1 := '1'B;
|
||||
pars.cm2.a5_1 := '1'B;
|
||||
pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
|
||||
pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
|
||||
f_init_handler(pars, 15.0);
|
||||
|
||||
/* cannot use f_perform_lu() as we expect a reject */
|
||||
var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi);
|
||||
f_create_gsup_expect(hex2str(g_pars.imsi));
|
||||
f_bssap_compl_l3(l3_lu);
|
||||
BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
|
||||
f_mm_auth();
|
||||
alt {
|
||||
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) { }
|
||||
[] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?,?)) {
|
||||
setverdict(fail, "CipherModeCommand despite no A5 intersection");
|
||||
self.stop;
|
||||
}
|
||||
[] BSSAP.receive {
|
||||
setverdict(inconc, "Unknown/unexpected BSSAP received");
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
setverdict(pass);
|
||||
}
|
||||
testcase TC_lu_imsi_auth_tmsi_encr_13_2() runs on MTC_CT {
|
||||
var BSC_ConnHdlr vc_conn;
|
||||
f_init();
|
||||
f_vty_config(MSCVTY, "network", "authentication required");
|
||||
f_vty_config(MSCVTY, "network", "encryption a5 1 3");
|
||||
|
||||
vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_13_2), testcasename(), 35);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
/* A5/0 + A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
|
||||
private function f_tc_lu_imsi_auth_tmsi_encr_013_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
|
||||
pars.net.expect_auth := true;
|
||||
pars.net.expect_ciph := true;
|
||||
pars.net.kc_support := '0B'O; /* A5/1 + A5/3 */
|
||||
pars.cm1.a5_1 := '1'B;
|
||||
pars.cm2.a5_1 := '1'B;
|
||||
pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
|
||||
pars.cm2.classmarkInformationType2_oct5.a5_2 := '1'B;
|
||||
f_init_handler(pars, 15.0);
|
||||
f_perform_lu(true);
|
||||
}
|
||||
testcase TC_lu_imsi_auth_tmsi_encr_013_2() runs on MTC_CT {
|
||||
var BSC_ConnHdlr vc_conn;
|
||||
f_init();
|
||||
f_vty_config(MSCVTY, "network", "authentication required");
|
||||
f_vty_config(MSCVTY, "network", "encryption a5 0 1 3");
|
||||
|
||||
vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_013_2), testcasename(), 36);
|
||||
vc_conn.done;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO:
|
||||
|
@ -1487,6 +1625,11 @@ control {
|
|||
execute( TC_mt_crcx_ran_reject() );
|
||||
execute( TC_mt_t310() );
|
||||
execute( TC_gsup_cancel() );
|
||||
execute( TC_lu_imsi_auth_tmsi_encr_1_13() );
|
||||
execute( TC_lu_imsi_auth_tmsi_encr_3_13() );
|
||||
execute( TC_lu_imsi_auth_tmsi_encr_3_1() );
|
||||
execute( TC_lu_imsi_auth_tmsi_encr_13_2() );
|
||||
execute( TC_lu_imsi_auth_tmsi_encr_013_2() );
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue