Hoernchen has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/24247 )

Change subject: msc: add first a5/4 tests
......................................................................

msc: add first a5/4 tests

All msc tests involving classmarks suffer from the same problem: if a
existing subscriber is reused the old classmarks will stick, since the
msc only overwrites updated parts of the cm when receiving a new cm, so
"downgrading" the existing classmark information is not possible.

This is circumvented here here by using different imsi suffixes,
the last param passed to f_start_handler.

Additionally the handler will now properly respond to cm requests
by the msc, i.e. in case the early cm is not sufficient for a5/4
because it lacks cm3, so the msc attempts once to query the cm,
hoping to get a cm3.

Related: SYS#5324
Change-Id: Idc055a006b325f58a5eafa88bc4415181b3500a2
---
M library/BSSMAP_Templates.ttcn
M msc/BSC_ConnectionHandler.ttcn
M msc/MSC_Tests.ttcn
M msc/expected-results.xml
M msc/gen_links.sh
M msc/regen_makefile.sh
6 files changed, 165 insertions(+), 6 deletions(-)

Approvals:
  Hoernchen: Looks good to me, approved; Verified
  pespin: Looks good to me, but someone else must approve
  laforge: Looks good to me, but someone else must approve



diff --git a/library/BSSMAP_Templates.ttcn b/library/BSSMAP_Templates.ttcn
index 1949fd6..c6698b1 100644
--- a/library/BSSMAP_Templates.ttcn
+++ b/library/BSSMAP_Templates.ttcn
@@ -1498,6 +1498,13 @@
        }
 }

+
+template BSSMAP_IE_ClassmarkInformationType3 ts_CM3_default := {
+       elementIdentifier := '13'O,
+       lengthIndicator := 0,   /* overwritten */
+       classmark3ValuePart := '01'O /* A5/4 supported */
+}
+
 template PDU_BSSAP ts_BSSMAP_ClassmarkUpd(template 
BSSMAP_IE_ClassmarkInformationType2 cm2 := ts_CM2_default,
                                          template 
BSSMAP_IE_ClassmarkInformationType3 cm3 := omit)
 modifies ts_BSSAP_BSSMAP := {
@@ -1540,6 +1547,18 @@
        }
 }

+template PDU_BSSAP tr_BSSMAP_ClassmarkRequest
+modifies tr_BSSAP_BSSMAP := {
+       pdu := {
+               bssmap := {
+                       classmarkRequest := {
+                               messageType := '58'O,
+                               talkerPriority := *
+                       }
+               }
+       }
+}
+
 /* return Layer3 octetstring inside BSSAP PDU */
 function f_bssap_extract_l3(PDU_BSSAP bssap) return template octetstring {
        if (ischosen(bssap.pdu.bssmap)) {
diff --git a/msc/BSC_ConnectionHandler.ttcn b/msc/BSC_ConnectionHandler.ttcn
index 8ca8264..8eb3f73 100644
--- a/msc/BSC_ConnectionHandler.ttcn
+++ b/msc/BSC_ConnectionHandler.ttcn
@@ -12,6 +12,7 @@

 module BSC_ConnectionHandler {

+import from TCCOpenSecurity_Functions all;
 import from General_Types all;
 import from Osmocom_Types all;
 import from Native_Functions all;
@@ -111,7 +112,7 @@
 };

 /* get a one-octet bitmaks of supported algorithms based on Classmark 
information */
-function f_alg_mask_from_cm(BSSMAP_IE_ClassmarkInformationType2 cm2) return 
OCT1 {
+function f_alg_mask_from_cm(BSSMAP_IE_ClassmarkInformationType2 cm2, template 
(omit) BSSMAP_IE_ClassmarkInformationType3 cm3 := omit) return OCT1 {
        var BIT8 res := '00000001'B;    /* A5/0 always supported */

        if (cm2.a5_1 == '0'B) {
@@ -123,7 +124,12 @@
        if (cm2.classmarkInformationType2_oct5.a5_3 == '1'B) {
                res := res or4b '00001000'B;
        }
-       /* TODO: CM3 for A5/4 and beyond */
+       if (not istemplatekind(cm3, "omit")) {
+               var BSSMAP_IE_ClassmarkInformationType3 v := valueof(cm3);
+               var BIT8 tmp := oct2bit(v.classmark3ValuePart[0]) and4b 
'00001111'B;
+               res := res or4b (tmp << 4);
+       }
+
        return bit2oct(res);
 }

@@ -155,6 +161,15 @@
        return -1;
 }

+/* return true for A5/x supported by OCT1 bitmask */
+function f_alg_supported_by_mask(OCT1 mask_in, integer whicha5) return boolean 
{
+       var BIT8 mask := oct2bit(mask_in);
+       if (mask and4b ('00000001'B << whicha5) != '00000000'B) {
+               return true;
+       }
+       return false;
+}
+
 /* altstep for the global guard timer */
 private altstep as_Tguard() runs on BSC_ConnHdlr {
        [] g_Tguard.timeout {
@@ -420,6 +435,7 @@
                                                                g_pars.vec.autn,
                                                                
g_pars.vec.res));
                GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
+               g_pars.vec.kc := f_auth3g_kc();
        } else {
                g_pars.vec := f_gen_auth_vec_2g();
                auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(g_pars.vec.rand,
@@ -532,15 +548,49 @@
        }
 }

+function f_auth3g_kc() runs on BSC_ConnHdlr return OCT8 {
+       var integer i;
+       var octetstring res := g_pars.vec.ck[0] xor4b g_pars.vec.ck[0 + 8] 
xor4b g_pars.vec.ik[0] xor4b g_pars.vec.ik[0 + 8];
+       for (i := 1; i < 8; i := i + 1) {
+               var octetstring a := g_pars.vec.ck[i] xor4b g_pars.vec.ck[i + 
8] xor4b g_pars.vec.ik[i] xor4b g_pars.vec.ik[i + 8];
+               res := res & a;
+       }
+
+       return res;
+}
+
+
 function f_mm_common() runs on BSC_ConnHdlr
 {
        f_mm_auth();
        if (g_pars.ran_is_geran) {
                if (g_pars.net.expect_ciph) {
-                       var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
+                       var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2, 
g_pars.cm3);
                        var OCT1 a5_intersect := g_pars.net.kc_support and4b 
a5_net;
+                       var boolean has_a54 := 
f_alg_supported_by_mask(a5_intersect, 4);
+
+                       var PDU_BSSAP pdu;
                        alt {
-                       [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, 
g_pars.vec.kc)) {
+                               [] 
BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) -> value 
pdu {
+                               var PDU_BSSMAP_CipherModeCommand ciphmodcmd := 
pdu.pdu.bssmap.cipherModeCommand;
+                               if (g_pars.use_umts_aka and has_a54) {
+                                       var OCT32 fulloutput := 
f_calculate_HMAC_SHA256(g_pars.vec.ck & g_pars.vec.ik, '32'O, 32);
+                                       var OCT16 kc128 := substr(fulloutput, 
0, 16);
+                                       if (not ispresent(ciphmodcmd.kC128)) {
+                                               setverdict(fail, "kc128 missing 
in CiphModCmd");
+                                               mtc.stop;
+                                       }
+                                       if (ciphmodcmd.kC128.kC128_Value != 
kc128) {
+                                               setverdict(fail, "kc128 wrong 
in CiphModCmd?!", kc128);
+                                               mtc.stop;
+                                       }
+                               } else {
+                                       if (ispresent(ciphmodcmd.kC128)) {
+                                               setverdict(fail, "kc128 present 
in CiphModCmd, but should not exist!");
+                                               mtc.stop;
+                                       }
+                               }
+
                                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)));
@@ -549,6 +599,10 @@
                                setverdict(fail, "Wrong ciphering algorithm 
mask in CiphModCmd");
                                mtc.stop;
                                }
+                       [] BSSAP.receive(tr_BSSMAP_ClassmarkRequest) {
+                               BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, 
g_pars.cm3))
+                               repeat;
+                               }
                        }
                        /* FIXME: Send the best available algorithm */
                }
diff --git a/msc/MSC_Tests.ttcn b/msc/MSC_Tests.ttcn
index 0fdc376..b791782 100644
--- a/msc/MSC_Tests.ttcn
+++ b/msc/MSC_Tests.ttcn
@@ -2009,6 +2009,84 @@
        vc_conn.done;
 }

+/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with only 
A5/1 support */
+private function f_tc_lu_imsi_auth_tmsi_encr_0134_1(charstring id, 
BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+       pars.net.expect_auth := true;
+       pars.net.expect_ciph := true;
+       pars.net.kc_support := '03'O;   /*  A5/0 + A5/1 */
+       pars.cm1.a5_1 := '0'B;
+       pars.cm2.a5_1 := '0'B;
+       pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
+       pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
+       pars.cm2.classmarkInformationType2_oct5.cm3 := '0'B;
+       pars.cm3 := omit;
+       pars.use_umts_aka := true;
+
+       f_init_handler(pars, 15.0);
+       f_perform_lu();
+}
+testcase TC_lu_imsi_auth_tmsi_encr_0134_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 0 1 3 4");
+
+       vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_1), 
39);
+       vc_conn.done;
+}
+
+/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with A5/3 
+ A5/4 support */
+private function f_tc_lu_imsi_auth_tmsi_encr_0134_34(charstring id, 
BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+       pars.net.expect_auth := true;
+       pars.net.expect_ciph := true;
+       pars.net.kc_support := '19'O;   /* A5/3 + A5/4 */
+       pars.cm1.a5_1 := '1'B;
+       pars.cm2.a5_1 := '1'B;
+       pars.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
+       pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
+       pars.cm2.classmarkInformationType2_oct5.cm3 := '1'B;
+       pars.cm3 := valueof(ts_CM3_default);
+       pars.use_umts_aka := true;
+
+       f_init_handler(pars, 15.0);
+       f_perform_lu();
+}
+testcase TC_lu_imsi_auth_tmsi_encr_0134_34() 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 4");
+
+       vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_34), 
40);
+       vc_conn.done;
+}
+
+/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with A5/3 
support but no CM3 */
+private function f_tc_lu_imsi_auth_tmsi_encr_0134_34_no_cm3(charstring id, 
BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+       pars.net.expect_auth := true;
+       pars.net.expect_ciph := true;
+       pars.net.kc_support := '19'O;   /* A5/3 + A5/4 */
+       pars.cm1.a5_1 := '1'B;
+       pars.cm2.a5_1 := '1'B;
+       pars.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
+       pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
+       pars.cm2.classmarkInformationType2_oct5.cm3 := '0'B;
+       pars.cm3 := omit;
+       pars.use_umts_aka := true;
+
+       f_init_handler(pars, 15.0);
+       f_perform_lu();
+}
+testcase TC_lu_imsi_auth_tmsi_encr_0134_34_no_cm3() 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 4");
+
+       vc_conn := 
f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_34_no_cm3), 41);
+       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;
@@ -6458,6 +6536,10 @@
        execute( TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() );
        execute( TC_lu_imsi_auth_tmsi_encr_13_2() );
        execute( TC_lu_imsi_auth_tmsi_encr_013_2() );
+       execute( TC_lu_imsi_auth_tmsi_encr_0134_1() );
+       execute( TC_lu_imsi_auth_tmsi_encr_0134_34() );
+       execute( TC_lu_imsi_auth_tmsi_encr_0134_34_no_cm3() );
+
        execute( TC_mo_release_timeout() );
        execute( TC_lu_and_mt_call_no_dlcx_resp() );
        execute( TC_reset_two() );
diff --git a/msc/expected-results.xml b/msc/expected-results.xml
index a01cd22..4e2eeba 100644
--- a/msc/expected-results.xml
+++ b/msc/expected-results.xml
@@ -56,6 +56,9 @@
   <testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_3_1_no_cm' 
time='MASKED'/>
   <testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_13_2' 
time='MASKED'/>
   <testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_013_2' 
time='MASKED'/>
+  <testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_0134_1' 
time='MASKED'/>
+  <testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_0134_34' 
time='MASKED'/>
+  <testcase classname='MSC_Tests' 
name='TC_lu_imsi_auth_tmsi_encr_0134_34_no_cm3' time='MASKED'/>
   <testcase classname='MSC_Tests' name='TC_mo_release_timeout' time='MASKED'/>
   <testcase classname='MSC_Tests' name='TC_lu_and_mt_call_no_dlcx_resp' 
time='MASKED'/>
   <testcase classname='MSC_Tests' name='TC_reset_two' time='MASKED'/>
diff --git a/msc/gen_links.sh b/msc/gen_links.sh
index 221110e..b112a67 100755
--- a/msc/gen_links.sh
+++ b/msc/gen_links.sh
@@ -11,6 +11,7 @@
 DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
 FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn 
TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
 FILES+=" TCCEncoding_Functions.ttcn TCCEncoding.cc " # GSM 7-bit coding
+FILES+=" TCCOpenSecurity_Functions.ttcn TCCOpenSecurity.cc 
TCCOpenSecurity_Functions.hh"
 gen_links $DIR $FILES

 DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
diff --git a/msc/regen_makefile.sh b/msc/regen_makefile.sh
index 6ee3ef5..cbb491d 100755
--- a/msc/regen_makefile.sh
+++ b/msc/regen_makefile.sh
@@ -1,9 +1,9 @@
 #!/bin/sh

-FILES="*.ttcn *.ttcnpp SCCP_EncDec.cc  SCTPasp_PT.cc  TCCConversion.cc 
TCCInterface.cc UD_PT.cc MNCC_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc 
SDP_EncDec.cc RTP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc 
RTP_CodecPort_CtrlFunctDef.cc MGCP_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc 
Native_FunctionDefs.cc SMPP_EncDec.cc SMPP_CodecPort_CtrlFunctDef.cc 
MAP_EncDec.cc SS_EncDec.cc TCCEncoding.cc SGsAP_CodecPort_CtrlFunctDef.cc 
RANAP_EncDec.cc *.c *.asn"
+FILES="*.ttcn *.ttcnpp SCCP_EncDec.cc  SCTPasp_PT.cc  TCCConversion.cc 
TCCInterface.cc UD_PT.cc MNCC_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc 
SDP_EncDec.cc RTP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc 
RTP_CodecPort_CtrlFunctDef.cc MGCP_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc 
Native_FunctionDefs.cc SMPP_EncDec.cc SMPP_CodecPort_CtrlFunctDef.cc 
MAP_EncDec.cc SS_EncDec.cc TCCEncoding.cc SGsAP_CodecPort_CtrlFunctDef.cc 
RANAP_EncDec.cc TCCOpenSecurity.cc *.c *.asn"

 export CPPFLAGS_TTCN3="-DIPA_EMULATION_MGCP -DIPA_EMULATION_CTRL 
-DIPA_EMULATION_GSUP -DIPA_EMULATION_SCCP -DRAN_EMULATION_BSSAP 
-DRAN_EMULATION_MGCP -DRAN_EMULATION_CTRL -DRAN_EMULATION_RANAP 
-DUSE_MTP3_DISTRIBUTOR"

 ../regen-makefile.sh MSC_Tests.ttcn $FILES

-sed -i -e 's/^LINUX_LIBS = -lxml2 -lsctp/LINUX_LIBS = -lxml2 -lsctp 
-lfftranscode/' Makefile
+sed -i -e 's/^LINUX_LIBS = -lxml2 -lsctp/LINUX_LIBS = -lxml2 -lsctp 
-lfftranscode -lssl/' Makefile

--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/24247
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: Idc055a006b325f58a5eafa88bc4415181b3500a2
Gerrit-Change-Number: 24247
Gerrit-PatchSet: 4
Gerrit-Owner: Hoernchen <ew...@sysmocom.de>
Gerrit-Reviewer: Hoernchen <ew...@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <lafo...@osmocom.org>
Gerrit-Reviewer: pespin <pes...@sysmocom.de>
Gerrit-CC: fixeria <vyanits...@sysmocom.de>
Gerrit-MessageType: merged

Reply via email to