Skip to content

Commit 8e9e511

Browse files
committed
corenet: restore good working conditions for the 4G part of corenet
1 parent 4cbe404 commit 8e9e511

File tree

7 files changed

+94
-63
lines changed

7 files changed

+94
-63
lines changed

pycrate_corenet/AuC.db

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# file used by ServerAuC.py
66
#
77
# csv'style file, with the following fields:
8-
# - IMSI (digits);
8+
# - IMSI (15 or 16 digits);
99
# - K (hex), subscriber authentication key,
1010
# 16-bytes when using Milenage or comp128
1111
# 16 or 32-bytes when using TUAK;

pycrate_corenet/HdlrUES1.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class UEEMMd(SigStack):
9090
# Unit: 0: 2s, 1: 1mn, 2: 6mn, 7: deactivated
9191
_T3412 = {'Unit': 2, 'Value': 2} # 12mn
9292
#_T3412 = {'Unit': 7, 'Value': 0} # deactivated
93-
#
93+
#
9494
# Reattach attempt after a failure timer: dict {'Unit': uint3, 'Value': uint5}
9595
# Unit: 0: 2s, 1: 1mn, 2: 6mn, 7: deactivated
9696
_T3402 = {'Unit': 1, 'Value': 2} # 2mn
@@ -379,7 +379,7 @@ def clear(self):
379379
def require_auth(self, Proc, ksi=None):
380380
# ksi is a 2-tuple (TSC 0..1, Value 0..7)
381381
# check if an EMMAuthentication procedure is required
382-
if self.S1.SECNAS_DISABLED or self.AUTH_DISABLED:
382+
if self.AUTH_DISABLED:
383383
return False
384384
elif ksi is None or ksi[1] == 7:
385385
self.S1.SEC['KSI'] = None
@@ -426,7 +426,7 @@ def require_auth(self, Proc, ksi=None):
426426

427427
def require_smc(self, Proc):
428428
# check if an EMMSecurityModeControl procedure is required
429-
if self.S1.SECNAS_DISABLED or self.SMC_DISABLED:
429+
if self.SMC_DISABLED:
430430
return False
431431
#
432432
elif ProcAbbrLUT[Proc.Name] in self.SMC_DISABLED_PROC:
@@ -602,7 +602,7 @@ def _get_sec_eia(self):
602602
if UESecCap._content[8+eia].get_val():
603603
return eia
604604
self._log('INF', 'no matching EIA identifier, using EIA%i' % self.SMC_EIA_DEF)
605-
return self.SMC_EEA_DEF
605+
return self.SMC_EIA_DEF
606606

607607
#--------------------------------------------------------------------------#
608608
# network-initiated method (fg task, to be used from the interpreter)
@@ -668,14 +668,14 @@ def req_ident(self, idtype=NAS.IDTYPE_IMSI):
668668
"""
669669
return self.run_proc(EMMIdentification, IDType=idtype)
670670

671-
def detach(self, type=1, cause=None):
671+
def detach(self, typ=1, cause=None):
672672
"""send an EMM Detach with type and cause (optional) and wait for the
673673
response or timeout
674674
"""
675675
if cause is not None:
676-
return self.run_proc(EMMDetachCN, EPSDetachTypeMT={'Type': type}, EMMCause=cause)
676+
return self.run_proc(EMMDetachCN, EPSDetachType={'Type': typ}, EMMCause=cause)
677677
else:
678-
return self.run_proc(EMMDetachCN, EPSDetachTypeMT={'Type': type})
678+
return self.run_proc(EMMDetachCN, EPSDetachType={'Type': typ})
679679

680680
def inform(self, **info):
681681
"""send an EMM information with given info
@@ -993,8 +993,8 @@ def process_trans(self, trans_id):
993993
# 2.2) check the protocol config options
994994
if trans['ProtConfig']:
995995
IEs['ProtConfig'], pdnaddrreq = self.process_protconfig(pdncfg, trans['ProtConfig'])
996-
if not pdnaddrreq:
997-
IEs['PDNAddr'] = b''
996+
#if not pdnaddrreq:
997+
# IEs['PDNAddr'] = b''
998998
#
999999
if 'NBIFOMContainer' in trans:
10001000
self._log('WNG', 'NBIFOMContainer IE unsupported')
@@ -1124,9 +1124,9 @@ class UES1d(SigStack):
11241124
#--------------------------------------------------------------------------#
11251125
# global security policy
11261126
#--------------------------------------------------------------------------#
1127-
# this will systematically bypass all auth and smc procedures,
1128-
# NAS MAC and UL count verification in the uplink
1129-
# and setting of the EMM security header (and encryption) in the downlink
1127+
# this will systematically bypass the NAS security layer:
1128+
# - NAS MAC and UL count verification in the uplink
1129+
# - setting of the EMM security header (and encryption) in the downlink
11301130
SECNAS_DISABLED = False
11311131
#
11321132
# finer grained NAS security checks:
@@ -1141,6 +1141,11 @@ class UES1d(SigStack):
11411141
# in the downlink for given NAS message (by name)
11421142
SECNAS_PDU_NOSEC = set()
11431143
#
1144+
# to force EEA0 despite the selected encryption algorithm for DL NAS messages
1145+
SECNAS_FORCE_EEA0 = False
1146+
# to force EIA0 despite the selected IP algorithm for DL NAS messages
1147+
SECNAS_FORCE_EIA0 = False
1148+
#
11441149
# format of the security context dict self.SEC:
11451150
# self.SEC is a dict of available 3G / 4G security contexts indexed by KSI,
11461151
# and current KSI in use
@@ -1539,8 +1544,10 @@ def process_nas_sec_servreq(self, ServReq):
15391544
else:
15401545
self.SEC['KSI'] = ue_ksi
15411546
secctx = self.SEC[ue_ksi]
1542-
#
1547+
if 'Knasint' not in secctx:
1548+
self.EMM.set_sec_ctx_smc(ue_ksi)
15431549
sqnmsb, sqnlsb = secctx['UL'] & 0xffffffe0, secctx['UL'] & 0x1f
1550+
#
15441551
verif_mac = ServReq.mac_verify(secctx['Knasint'], 0, secctx['EIA'], sqnmsb)
15451552
verif_sqn = True if ue_sqn == sqnlsb else False
15461553
#
@@ -1725,8 +1732,7 @@ def output_nas_sec(self, NasTx):
17251732
"""
17261733
if self.UE.TRACE_NAS_EPS:
17271734
self._log('TRACE_NAS_EPS_DL', '\n' + NasTx.show())
1728-
if self.SECNAS_DISABLED or NasTx._name in self.SECNAS_PDU_NOSEC or \
1729-
NasTx._sec == False:
1735+
if self.SECNAS_DISABLED or NasTx._name in self.SECNAS_PDU_NOSEC or NasTx._sec == False:
17301736
sec = False
17311737
else:
17321738
ksi = self.SEC['KSI']
@@ -1742,6 +1748,8 @@ def output_nas_sec(self, NasTx):
17421748
return None
17431749
else:
17441750
secctx = self.SEC[self.SEC['KSI']]
1751+
if 'Knasint' not in secctx:
1752+
self.EMM.set_sec_ctx_smc(ksi)
17451753
sqnmsb, sqnlsb = secctx['DL'] & 0xffffff00, secctx['DL'] & 0xff
17461754
if NasTx._name == 'EMMSecurityModeCommand':
17471755
# integrity protextion only + new security context
@@ -1753,11 +1761,12 @@ def output_nas_sec(self, NasTx):
17531761
NasTxSec = NAS.EMMSecProtNASMessage(val={'EMMHeaderSec': {'SecHdr': sh},
17541762
'Seqn': sqnlsb,
17551763
'NASMessage': NasTx.to_bytes()})
1756-
if sh == 2:
1764+
if sh == 2 and not self.SECNAS_FORCE_EEA0:
17571765
NasTxSec.encrypt(secctx['Knasenc'], 1, secctx['EEA'], sqnmsb)
1758-
NasTxSec.mac_compute(secctx['Knasint'], 1, secctx['EIA'], sqnmsb)
1759-
except Exception:
1760-
self._log('ERR', 'NAS SEC DL: unable to protect the NAS message %s' % NasTx._name)
1766+
if not self.SECNAS_FORCE_EIA0:
1767+
NasTxSec.mac_compute(secctx['Knasint'], 1, secctx['EIA'], sqnmsb)
1768+
except Exception as err:
1769+
self._log('ERR', 'NAS SEC DL: unable to protect the NAS message %s: %r' % (NasTx._name, err))
17611770
#self.reset_sec_ctx()
17621771
return None
17631772
else:
@@ -1789,7 +1798,7 @@ def ret_s1ap_dnt(self, NasTx, **IEs):
17891798
if buf is None:
17901799
return self._s1ap_nas_sec_err()
17911800
IEs['NAS_PDU'] = buf
1792-
NgapProc = self.init_ngap_proc(NGAPDownlinkNASTransport, **IEs)
1801+
S1apProc = self.init_s1ap_proc(S1APDownlinkNASTransport, **IEs)
17931802
if S1apProc:
17941803
return [S1apProc]
17951804
else:

pycrate_corenet/ProcCNEMM.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ def output(self):
646646
if self.UE.IMEISV is None and self.EMM.SMC_IMEISV_REQ:
647647
IEs['IMEISVReq'] = 1
648648
# TODO: check support of NonceUE / NonceMME for mobility procedures
649+
# TODO: check support for UE Additional Security Capabilities
649650
#
650651
self.set_msg(7, 93, **IEs)
651652
self.encode_msg(7, 93)
@@ -1013,7 +1014,7 @@ def output(self):
10131014
# prepare the TAIList for the UE:
10141015
# it only contains a single PartialTAIList of type 0 with the TAI of the eNB
10151016
# to which the UE is connected
1016-
tailist = [{'Type':0, 'PLMN':self.UE.PLMN, 'TACValues':[self.UE.TAC]}]
1017+
tailist = [{'Type':0, 'PTAI':{'PLMN':self.UE.PLMN, 'TACs':[self.UE.TAC]}}]
10171018
#
10181019
# prepare AttachAccept IEs
10191020
IEs = {'EPSAttachResult': self.att_type,
@@ -1235,7 +1236,7 @@ def output(self):
12351236
self._pdu.append( (time(), 'DL', self._nas_tx) )
12361237
self._log('INF', self._nas_tx['EPSDetachType'].repr())
12371238
# in case of IMSI-detach, a TAU with IMSI attach is expected in response
1238-
if self._nas_tx['EPSDetachType']['Type'].get_val() != 3:
1239+
if self._nas_tx['EPSDetachType']['EPSDetachTypeMT']['Type'].get_val() != 3:
12391240
self.init_timer()
12401241
else:
12411242
self.rm_from_emm_stack()

pycrate_corenet/ProcCNESM.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def set_msg(self, pd, typ, **kw):
131131

132132
def output(self):
133133
self._log('ERR', 'output() not implemented')
134-
return None
134+
return []
135135

136136
def process(self, pdu):
137137
if self.TRACK_PDU:
@@ -140,12 +140,12 @@ def process(self, pdu):
140140
self.decode_msg(pdu, self.UEInfo)
141141
#
142142
self._log('ERR', 'process() not implemented')
143-
return None
143+
return []
144144

145145
def postprocess(self, Proc=None):
146146
self._log('ERR', 'postprocess() not implemented')
147147
self.rm_from_esm_stack()
148-
return None
148+
return []
149149

150150
def abort(self):
151151
# abort this procedure, and all procedures started within this one

pycrate_corenet/ServerAuC.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
HOWTO:
3232
3333
1) in order to use AuC, the following parameters and files need to be configured:
34-
-> files AuC.db need to be edited with IMSI and authentication parameters from your (U)SIM cards
35-
-> AuC.AUC_DB_PATH can be change if the AuC.db file is put elsewhere
34+
-> file AuC.db needs to be edited with IMSI and authentication parameters from your (U)SIM cards
35+
-> AuC.AUC_DB_PATH can be changed if the AuC.db file is put elsewhere, it refers to the directory in which AuC.db lies
3636
-> AuC.OP needs to be changed according to your Milenage customization
3737
3838
2) To use the AuC (in case your IMSI is '001010000000001'):
@@ -160,7 +160,7 @@ def __init__(self):
160160
db_fd = open('%sAuC.db' % self.AUC_DB_PATH, 'r')
161161
# parse it into a dict object with IMSI as key
162162
for line in db_fd.readlines():
163-
if line[0] != '#' and line.count(';') >= 3:
163+
if line and line[0] != '#' and line.count(';') >= 3:
164164
fields = line[:-1].split(';')
165165
IMSI = str( fields[0] )
166166
K = unhexlify( fields[1].encode('ascii') )
@@ -320,14 +320,10 @@ def make_3g_vector(self, IMSI, AMF=b'\0\0', RAND=None):
320320
K, ALG, SQN = K_ALG_SQN_OP
321321
OP = None
322322
#
323-
if SQN == -1:
324-
# Milenage / TUAK not supported
325-
self._log('WNG', '[make_3g_vector] IMSI %s does not support Milenage / TUAK' % IMSI)
326-
return None
327-
#
328323
# increment SQN counter in the db
329-
K_ALG_SQN_OP[2] += 1
330-
self._save_required = True
324+
if SQN >= 0:
325+
K_ALG_SQN_OP[2] += 1
326+
self._save_required = True
331327
#
332328
# pack SQN from integer to a 48-bit buffer
333329
SQNb = pack('>Q', SQN)[2:]

0 commit comments

Comments
 (0)