pespin has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/35570?usp=email )

Change subject: mme: Add code to derive NAS token from NAS ul_count
......................................................................

mme: Add code to derive NAS token from NAS ul_count

NAS Token is derived from kasme and NAS ul_count as specified in 3GPP TS
33.401 A.9, and its LSB 16 bits passed to the network when mapping the GUTI to
RAI+PTMSI+PTIMSI_SIG.

Take the chance to move guti2rai_ptmsi() up to before the place it is
used.
Change-Id: I5e6003a2fe3e74cc93cfe4a288e6c114aa288d0b
---
M library/S1AP_Emulation.ttcn
M mme/LTE_CryptoFunctionDefs.cc
M mme/LTE_CryptoFunctions.ttcn
M mme/MME_Tests.ttcn
M mme/key_derivation.c
M mme/key_derivation.h
6 files changed, 100 insertions(+), 37 deletions(-)

Approvals:
  Jenkins Builder: Verified
  fixeria: Looks good to me, but someone else must approve
  daniel: Looks good to me, approved




diff --git a/library/S1AP_Emulation.ttcn b/library/S1AP_Emulation.ttcn
index 1ef4a76..e3e3216 100644
--- a/library/S1AP_Emulation.ttcn
+++ b/library/S1AP_Emulation.ttcn
@@ -438,6 +438,7 @@
                var S1APEM_Config s1cfg;
                var charstring vlr_name, mme_name;
                var integer ai;
+               var octetstring kasme;

                alt {
                /* Configuration primitive from client */
@@ -544,8 +545,13 @@
                        f_create_expect_proc(procedureCode, vc_conn);
                        S1AP_PROC.reply(S1APEM_register_proc:{procedureCode, 
vc_conn}) to vc_conn;
                        }
+               [] S1AP_PROC.getcall(S1APEM_derive_nas_token:{?, ?, -}) -> 
param(kasme, vc_conn) {
+                       var integer assoc_id := f_assoc_id_by_comp(vc_conn);
+                       var OCT32 nas_token := f_kdf_nas_token(kasme, 
S1apAssociationTable[assoc_id].nus.tx_count)
+                       S1apAssociationTable[assoc_id].nus.tx_count := 
S1apAssociationTable[assoc_id].nus.tx_count + 1;
+                       S1AP_PROC.reply(S1APEM_derive_nas_token:{kasme, 
vc_conn, nas_token}) to vc_conn;
+                       }
                }
-
        }
 }

@@ -566,10 +572,12 @@

 signature S1APEM_register(in MME_UE_S1AP_ID mme_id, in ENB_UE_S1AP_ID enb_id, 
in S1AP_ConnHdlr hdlr);
 signature S1APEM_register_proc(in integer procedureCode, in S1AP_ConnHdlr 
hdlr);
+signature S1APEM_derive_nas_token(in octetstring kasme, in S1AP_ConnHdlr hdlr, 
out OCT32 nas_token);

 type port S1APEM_PROC_PT procedure {
        inout S1APEM_register;
        inout S1APEM_register_proc;
+       inout S1APEM_derive_nas_token;
 } with { extension "internal" };

 /* Function that can be used as create_cb and will use the expect table */
@@ -669,6 +677,17 @@
        log(procedureCode);
 }

+/* Derive NAS Token (and post-increment ul_count): */
+function f_s1apem_derive_nas_token(in octetstring kasme) runs on S1AP_ConnHdlr 
return OCT32
+{
+       var OCT32 nas_token;
+       S1AP_PROC.call(S1APEM_derive_nas_token:{kasme, self, -}) {
+               [] S1AP_PROC.getreply(S1APEM_derive_nas_token:{kasme, self, ?}) 
-> param(nas_token) {
+                       return nas_token;
+               };
+       }
+}
+
 private function f_expect_table_init()
 runs on S1AP_Emulation_CT {
        var integer i;
diff --git a/mme/LTE_CryptoFunctionDefs.cc b/mme/LTE_CryptoFunctionDefs.cc
index da2d521..7f82224 100644
--- a/mme/LTE_CryptoFunctionDefs.cc
+++ b/mme/LTE_CryptoFunctionDefs.cc
@@ -184,6 +184,14 @@
        return OCTETSTRING(sizeof(kenb), kenb);
 }

+OCTETSTRING f__kdf__nas__token(const OCTETSTRING &kasme, const INTEGER 
&ul_count)
+{
+       TTCN_Buffer ttcn_buf_kasme(kasme);
+       uint8_t nas_token[32];
+
+       mme_kdf_nas_token(ttcn_buf_kasme.get_data(), (int)ul_count, nas_token);
+       return OCTETSTRING(sizeof(nas_token), nas_token);
+}


 } // namespace
diff --git a/mme/LTE_CryptoFunctions.ttcn b/mme/LTE_CryptoFunctions.ttcn
index 18a3755..f0ea990 100644
--- a/mme/LTE_CryptoFunctions.ttcn
+++ b/mme/LTE_CryptoFunctions.ttcn
@@ -40,6 +40,8 @@

 external function f_kdf_nh(in OCT16 kasme, in OCT32 sync_inp) return OCT32;

+external function f_kdf_nas_token(in OCT16 kasme, in integer ul_count) return 
OCT32;
+
 
/*********************************************************************************
  * mid-level API
  
*********************************************************************************/
diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn
index f4f41e2..50b89b3 100644
--- a/mme/MME_Tests.ttcn
+++ b/mme/MME_Tests.ttcn
@@ -83,6 +83,7 @@
        hexstring imsi,
        charstring ue_ip,
        NAS_EPS_Types.GUTI guti optional,
+       octetstring kasme optional,

        /* TEI (Control) local side, S11 (SGW) */
        OCT4    s11_teic_local,
@@ -289,6 +290,7 @@
                imsi := f_gen_imsi(imsi_suffix),
                ue_ip := "192.168.123.50",
                guti := omit,
+               kasme := omit,
                s11_teic_local := '00000000'O,
                s11_teic_remote := omit,
                s5c_teic_local := '00000000'O,
@@ -585,11 +587,11 @@
                const OCT3 plmn_id := '00F110'O;
                const OCT6 sqn := '000000000020'O;
                const OCT6 ak := substr(autn, 0, 6) xor4b sqn;
-               var octetstring kasme := f_kdf_kasme(ck, ik, plmn_id, sqn, ak);
+               g_pars.ue_pars.kasme := f_kdf_kasme(ck, ik, plmn_id, sqn, ak);
                var S1APEM_Config cfg := {
                        set_nas_keys := {
-                               k_nas_int := f_kdf_nas_int(1, kasme),
-                               k_nas_enc := f_kdf_nas_enc(1, kasme)
+                               k_nas_int := f_kdf_nas_int(1, 
g_pars.ue_pars.kasme),
+                               k_nas_enc := f_kdf_nas_enc(1, 
g_pars.ue_pars.kasme)
                        }
                };
                S1AP.send(cfg);
@@ -856,6 +858,31 @@
        }
 }

+
+/* 3GPP TS 23.401 D.3.5, TS 23.003 2.8.2.1 */
+private function guti2rai_ptmsi(in NAS_EPS_Types.GUTI guti, in OCT2 
truncated_nas_token, out RoutingAreaIdentity rai, out OCT4 ptmsi, out OCT3 
ptmsi_sig) runs on ConnHdlr {
+       var bitstring mtmsi_bits := oct2bit(guti.mTMSI);
+       var bitstring ptmsi_bits;
+       var bitstring ptmsi_sig_bits;
+
+       rai := valueof(ts_RoutingAreaIdentity(guti.mccDigit1 & guti.mccDigit2 & 
guti.mccDigit3,
+                                             guti.mncDigit3 & guti.mncDigit1 & 
guti.mncDigit2,
+                                             guti.mMEGI, guti.mMEC));
+       /* 3GPP TS 23.003 2.8.2.0: "P-TMSI shall be of 32 bits length where the 
two topmost bits are
+        * reserved and always set to '11'. Hence, for a UE which may handover 
to GERAN/UTRAN (based on
+        * subscription and UE capabilities), the corresponding bits in the 
M-TMSI are set to '11'"
+        */
+       ptmsi_bits := '11'B & substr(mtmsi_bits, 2, 6) & oct2bit(guti.mMEC) & 
substr(mtmsi_bits, 16, 16);
+       ptmsi_sig_bits := substr(mtmsi_bits, 8, 8) & 
oct2bit(truncated_nas_token);
+       ptmsi := bit2oct(ptmsi_bits);
+       ptmsi_sig := bit2oct(ptmsi_sig_bits);
+       /* TODO: The UE shall fill the remaining 2 octets of the <P-TMSI 
signature> according to clauses 9.1.1, 9.4.1, 10.2.1, or
+        * 10.5.1 of 3GPP TS.33.401 [89] , as appropriate, for RAU/Attach 
procedures.*/
+}
+
+/* Test UE attached to EUTRAN reselecting a GERAN cell. In this scenario, the
+ * new SGSN will attempt to obtain information of the UE from the old SGSN 
(MME)
+ * through Gn interface using SGSN Context Request/Response procedure 
(OS#6294). */
 private function f_gtp_sgsn_context_4g_to_2g(OCT4 new_sgsn_local_teid := 
'12345678'O) runs on ConnHdlr {
        var template (value) GTPC_PDUs SGSNContextReqPDU;
        var RoutingAreaIdentity rai;
@@ -864,7 +891,11 @@
        var Gtp1cUnitdata gtpc_pdu;
        var OCT4 old_mme_local_teid;

-       guti2rai_ptmsi(g_pars.ue_pars.guti, rai, ptmsi, ptmsi_sig);
+       /* Derive NAS Token (and post-increment ul_count): */
+       var OCT32 nas_token := f_s1apem_derive_nas_token(g_pars.ue_pars.kasme);
+       var OCT2 truncated_nas_token := substr(nas_token, 30, 2);
+
+       guti2rai_ptmsi(g_pars.ue_pars.guti, truncated_nas_token, rai, ptmsi, 
ptmsi_sig);

        SGSNContextReqPDU := ts_SGSNContextReqPDU(rai, new_sgsn_local_teid, 
f_inet_addr(mp_gn_local_ip),
                                                  ptmsi := ts_PTMSI(ptmsi), 
ptmsi_sig := ts_PTMSI_sig(ptmsi_sig));
@@ -880,10 +911,10 @@
                setverdict(pass);
                }
        [] GTP.receive {
-               setverdict(fail, "unexpected GTPC message from MME");
+                Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, 
log2str("unexpected GTPC message from MME"));
                }
        [] T.timeout {
-               setverdict(fail, "no SGSN Context Response from MME");
+                Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("no 
SGSN Context Response from MME"));
                }
        }

@@ -1312,36 +1343,6 @@
        vc_conn.done;
 }

-/* Test UE attached to EUTRAN reselecting a GERAN cell. In this scenario, the
- * new SGSN will attempt to obtain information of the UE from the old SGSN 
(MME)
- * through Gn interface using SGSN Context Request/Response procedure 
(OS#6294). */
-/* TS 23.003 2.8.2.1 */
-private function guti2rai_ptmsi(in NAS_EPS_Types.GUTI guti, out 
RoutingAreaIdentity rai, out OCT4 ptmsi, out OCT3 ptmsi_sig) runs on ConnHdlr {
-       var bitstring mtmsi_bits := oct2bit(guti.mTMSI);
-       var bitstring ptmsi_bits;
-       var bitstring ptmsi_sig_bits;
-
-       rai := valueof(ts_RoutingAreaIdentity(guti.mccDigit1 & guti.mccDigit2 & 
guti.mccDigit3,
-                                             guti.mncDigit3 & guti.mncDigit1 & 
guti.mncDigit2,
-                                             guti.mMEGI, guti.mMEC));
-       /* 3GPP TS 23.003 2.8.2.0: "P-TMSI shall be of 32 bits length where the 
two topmost bits are
-        * reserved and always set to '11'. Hence, for a UE which may handover 
to GERAN/UTRAN (based on
-        * subscription and UE capabilities), the corresponding bits in the 
M-TMSI are set to '11'"
-        */
-       ptmsi_bits := '11'B & substr(mtmsi_bits, 2, 6) & oct2bit(guti.mMEC) & 
substr(mtmsi_bits, 16, 16);
-       ptmsi_sig_bits := substr(mtmsi_bits, 8, 8) & oct2bit('0000'O);
-       ptmsi := bit2oct(ptmsi_bits);
-       ptmsi_sig := bit2oct(ptmsi_sig_bits);
-       /* TODO: The UE shall fill the remaining 2 octets of the <P-TMSI 
signature> according to clauses 9.1.1, 9.4.1, 10.2.1, or
-        * 10.5.1 of 3GPP TS.33.401 [89] , as appropriate, for RAU/Attach 
procedures.*/
-       /* TODO: 3GPP TS 33.401 9.1.1 The 16 least significant bits available in
-        * the P-TMSI signature field shall be filled with the truncated 
NAS-token
-        * according to 3GPP TS 23.003 [3].The truncated NAS-token is defined 
as the 16
-        * least significant bits of the NAS-token.
-        * The NAS-token is derived as specified in Annex A.9. The UE shall use 
the uplink NAS COUNT value that it would use
-        * in the next NAS message to calculate the NAS-token and increase the 
stored uplink NAS COUNT value by 1.*/
-       /* TODO: mMEC "also copied into the 8 Most Significant Bits of the NRI 
field within the P-TMSI" */
-}
 private function f_TC_ue_cell_reselect_eutran_to_geran(ConnHdlrPars pars) runs 
on ConnHdlr {
        f_init_handler(pars);
        f_gtp_register_imsi(g_pars.ue_pars.imsi);
diff --git a/mme/key_derivation.c b/mme/key_derivation.c
index 36e4c91..8d5d8a4 100644
--- a/mme/key_derivation.c
+++ b/mme/key_derivation.c
@@ -80,3 +80,19 @@

        gnutls_hmac_fast(GNUTLS_MAC_SHA256, k, 32, s, 14, kasme);
 }
+
+/* TS33.401 Annex A.9: NAS token derivation for inter-RAT mobility */
+void mme_kdf_nas_token(const uint8_t *kasme, uint32_t ul_count, uint8_t 
*nas_token)
+{
+       uint8_t s[7];
+
+       s[0] = 0x17; /* FC Value */
+
+       ul_count = htonl(ul_count);
+       memcpy(s+1, &ul_count, 4);
+
+       s[5] = 0x00;
+       s[6] = 0x04;
+
+       gnutls_hmac_fast(GNUTLS_MAC_SHA256, kasme, 32, s, 7, nas_token);
+}
diff --git a/mme/key_derivation.h b/mme/key_derivation.h
index 496f52b..ae15b65 100644
--- a/mme/key_derivation.h
+++ b/mme/key_derivation.h
@@ -19,3 +19,5 @@
 void mme_kdf_enb(const uint8_t *kasme, uint32_t ul_count, uint8_t *kenb);

 void mme_kdf_nh(const uint8_t *kasme, const uint8_t *sync_input, uint8_t 
*kenb);
+
+void mme_kdf_nas_token(const uint8_t *kasme, uint32_t ul_count, uint8_t 
*nas_token);

--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/35570?usp=email
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: I5e6003a2fe3e74cc93cfe4a288e6c114aa288d0b
Gerrit-Change-Number: 35570
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pes...@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillm...@sysmocom.de>
Gerrit-Reviewer: fixeria <vyanits...@sysmocom.de>
Gerrit-Reviewer: pespin <pes...@sysmocom.de>
Gerrit-MessageType: merged

Reply via email to