Add support for reading misc. MILENAGE parameters
We now can read * IDX, MAX_DELTA and AGE_LIMIT parameters * whether or not SQN, age and max delta are enforced * SEQ array * Authentication Counter
This commit is contained in:
parent
b7ec495145
commit
72cf09e620
|
@ -51,6 +51,7 @@ def helptext():
|
||||||
print " -C, --set-opc HEXSTRING ........ Set OPc value"
|
print " -C, --set-opc HEXSTRING ........ Set OPc value"
|
||||||
print " -k, --ki ....................... Show KI value"
|
print " -k, --ki ....................... Show KI value"
|
||||||
print " -K, --set-ki ................... Set KI value"
|
print " -K, --set-ki ................... Set KI value"
|
||||||
|
print " -s --seq-parameters ........... Show MILENAGE SEQ/SQN parameters"
|
||||||
print ""
|
print ""
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,15 +73,17 @@ def main(argv):
|
||||||
getopt_write_ki = None
|
getopt_write_ki = None
|
||||||
getopt_force = False
|
getopt_force = False
|
||||||
getopt_write_iccid = None
|
getopt_write_iccid = None
|
||||||
|
getopt_seq_par = False
|
||||||
|
|
||||||
# Analyze commandline options
|
# Analyze commandline options
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(argv,
|
opts, args = getopt.getopt(argv,
|
||||||
"hva:ucmtT:lL:oO:C:kK:fiI:",
|
"hva:ucmtT:lL:oO:C:kK:fiI:s",
|
||||||
["help","verbose","adm1=","usim","classic",
|
["help","verbose","adm1=","usim","classic",
|
||||||
"mode","auth","set-auth=","milenage",
|
"mode","auth","set-auth=","milenage",
|
||||||
"set-milenage","opc","set-op=","set-opc=",
|
"set-milenage","opc","set-op=","set-opc=",
|
||||||
"ki","set-ki=","force","iccid","set-iccid="])
|
"ki","set-ki=","force","iccid","set-iccid=",
|
||||||
|
"seq-parameters"])
|
||||||
except getopt.GetoptError:
|
except getopt.GetoptError:
|
||||||
print " * Error: Invalid commandline options"
|
print " * Error: Invalid commandline options"
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
@ -121,6 +124,8 @@ def main(argv):
|
||||||
getopt_force = True
|
getopt_force = True
|
||||||
elif opt in ("-I", "--set-iccid"):
|
elif opt in ("-I", "--set-iccid"):
|
||||||
getopt_write_iccid = asciihex_to_list(pad_asciihex(arg))
|
getopt_write_iccid = asciihex_to_list(pad_asciihex(arg))
|
||||||
|
elif opt in ("-s", "--sqe-parameters"):
|
||||||
|
getopt_seq_par = True
|
||||||
|
|
||||||
|
|
||||||
if not getopt_adm1:
|
if not getopt_adm1:
|
||||||
|
@ -185,6 +190,10 @@ def main(argv):
|
||||||
sysmo_usim_show_milenage_params(sim)
|
sysmo_usim_show_milenage_params(sim)
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
|
if getopt_seq_par:
|
||||||
|
print "Reading Milenage Sequence parameters..."
|
||||||
|
sysmo_usim_read_milenage_sqn_params(sim)
|
||||||
|
|
||||||
if getopt_write_op:
|
if getopt_write_op:
|
||||||
print "Writing OP value..."
|
print "Writing OP value..."
|
||||||
sysmo_usim_write_opc_params(sim, 0, getopt_write_op)
|
sysmo_usim_write_opc_params(sim, 0, getopt_write_op)
|
||||||
|
|
|
@ -60,6 +60,10 @@ SYSMO_USIMSJS1_EF_OPC = [0x00, 0xF7]
|
||||||
SYSMO_USIMSJS1_DF_AUTH = [0x7F, 0xCC] #FIXME: Manual does not mention name, just called it "DF_AUTH" might be wrong!
|
SYSMO_USIMSJS1_DF_AUTH = [0x7F, 0xCC] #FIXME: Manual does not mention name, just called it "DF_AUTH" might be wrong!
|
||||||
SYSMO_USIMSJS1_EF_AUTH = [0x6F, 0x00]
|
SYSMO_USIMSJS1_EF_AUTH = [0x6F, 0x00]
|
||||||
SYSMO_USIMSJS1_EF_MLNGC = [0x6F, 0x01]
|
SYSMO_USIMSJS1_EF_MLNGC = [0x6F, 0x01]
|
||||||
|
SYSMO_USIMSJS1_EF_SQNC = [0x00, 0xFB] # ADF.USIM
|
||||||
|
SYSMO_USIMSJS1_EF_SQNA = [0x00, 0xFA] # ADF.USIM
|
||||||
|
SYSMO_USIMSJS1_EF_EFMLNG = [0x00, 0xFB] # ADF.USIM
|
||||||
|
SYSMO_USIMSJS1_EF_AC = [0x00, 0xFE] # ADF.USIM
|
||||||
|
|
||||||
# CHV Types
|
# CHV Types
|
||||||
SYSMO_USIMSJS1_ADM1 = 0x0A
|
SYSMO_USIMSJS1_ADM1 = 0x0A
|
||||||
|
@ -131,6 +135,62 @@ class SYSMO_USIMSJS1_FILE_EF_MLNGC:
|
||||||
dump += " R5: " + str(hex(self.R5))
|
dump += " R5: " + str(hex(self.R5))
|
||||||
return dump
|
return dump
|
||||||
|
|
||||||
|
class SYSMO_USIMSJS1_FILE_EF_SQNC:
|
||||||
|
# Default parameters
|
||||||
|
ind_size_bits = 5
|
||||||
|
sqn_check_enabled = True
|
||||||
|
sqn_age_limit_enabled = True
|
||||||
|
sqn_max_delta_enabled = True
|
||||||
|
sqnms_offset = 0
|
||||||
|
max_delta = 0;
|
||||||
|
age_limit = 2**28 << ind_size_bits
|
||||||
|
|
||||||
|
def __init__(self, content = None):
|
||||||
|
if content == None:
|
||||||
|
return
|
||||||
|
if len(content) != 15:
|
||||||
|
raise ValueError("unexpected length of %u bytes", len(content))
|
||||||
|
self.ind_size_bits = content[0] >> 4
|
||||||
|
self.sqn_check_enabled = content[0] & 0x08
|
||||||
|
self.sqn_age_limit_enabled = bool(content[0] & 0x04)
|
||||||
|
self.sqn_max_delta_enabled = bool(content[0] & 0x02)
|
||||||
|
self.sqnms_offset = list_to_int(content[1:3])
|
||||||
|
self.max_delta = list_to_int(content[3:9]) >> self.ind_size_bits
|
||||||
|
self.age_limit = list_to_int(content[9:15]) >> self.ind_size_bits
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
pfx = " "
|
||||||
|
dump = ""
|
||||||
|
|
||||||
|
dump += "%sIND (bits): %u\n" % (pfx, self.ind_size_bits)
|
||||||
|
dump += "%sSQN Check enabled: %u\n" % (pfx, self.sqn_check_enabled)
|
||||||
|
dump += "%sSQN Age Limit enabled: %u\n" % (pfx, self.sqn_age_limit_enabled)
|
||||||
|
dump += "%sSQN Max Delta enabled: %u\n" % (pfx, self.sqn_max_delta_enabled)
|
||||||
|
dump += "%sSQNms Offset: %u\n" % (pfx, self.sqnms_offset)
|
||||||
|
dump += "%sMax Delta: %u\n" % (pfx, self.max_delta)
|
||||||
|
dump += "%sAge Limit: %u\n" % (pfx, self.age_limit)
|
||||||
|
return dump
|
||||||
|
|
||||||
|
class SYSMO_USIMSJS1_FILE_EF_SQNA:
|
||||||
|
seq_array = []
|
||||||
|
|
||||||
|
def __init__(self, content, ind = 5):
|
||||||
|
if content == None:
|
||||||
|
return
|
||||||
|
if len(content) != 6*(2**ind):
|
||||||
|
raise ValueError("unexpected length of %u bytes", len(content))
|
||||||
|
# read in the SEQ array
|
||||||
|
for i in range(0, 2**ind):
|
||||||
|
offset = 6*i;
|
||||||
|
self.seq_array.append(list_to_int(content[offset:offset+6]))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
pfx = " "
|
||||||
|
dump = ""
|
||||||
|
for i in range(len(self.seq_array)):
|
||||||
|
dump += "%sSEQ[%03d]: %u\n" % (pfx, i, self.seq_array[i])
|
||||||
|
return dump
|
||||||
|
|
||||||
|
|
||||||
# Initalize card (select master file)
|
# Initalize card (select master file)
|
||||||
def sysmo_usim_init(sim):
|
def sysmo_usim_init(sim):
|
||||||
|
@ -196,6 +256,38 @@ def sysmo_usim_write_auth_params(sim, algo_2g, algo_3g):
|
||||||
sim.select(SYSMO_USIMSJS1_EF_AUTH)
|
sim.select(SYSMO_USIMSJS1_EF_AUTH)
|
||||||
sim.update_binary([algo_2g,algo_3g])
|
sim.update_binary([algo_2g,algo_3g])
|
||||||
|
|
||||||
|
def sysmo_usim_get_auth_counter(sim):
|
||||||
|
sim.select(SYSMO_USIMSJS1_EF_AC)
|
||||||
|
res = sim.read_binary(4, offset=0)
|
||||||
|
ctr = list_to_int(res.apdu[0:4])
|
||||||
|
if ctr == 0:
|
||||||
|
return "LOCKED"
|
||||||
|
elif ctr == 0xFFFFFFFF:
|
||||||
|
return "DISABLED"
|
||||||
|
else:
|
||||||
|
return ctr
|
||||||
|
|
||||||
|
def sysmo_usim_read_milenage_sqn_params(sim):
|
||||||
|
sysmo_usim_init(sim)
|
||||||
|
|
||||||
|
sim.card.SELECT_ADF_USIM()
|
||||||
|
sim.select(SYSMO_USIMSJS1_EF_SQNC)
|
||||||
|
|
||||||
|
res = sim.read_binary(15, offset = 0)
|
||||||
|
ef_sqnc = SYSMO_USIMSJS1_FILE_EF_SQNC(res.apdu)
|
||||||
|
print "* Current SQN Configuration: "
|
||||||
|
print str(ef_sqnc)
|
||||||
|
|
||||||
|
# SQN Array
|
||||||
|
ind_pow = 2**ef_sqnc.ind_size_bits
|
||||||
|
sim.select(SYSMO_USIMSJS1_EF_SQNA)
|
||||||
|
res = sim.read_binary(ind_pow*6, offset=0)
|
||||||
|
ef_sqna = SYSMO_USIMSJS1_FILE_EF_SQNA(res.apdu)
|
||||||
|
print "* Current SQN Array: "
|
||||||
|
print str(ef_sqna)
|
||||||
|
|
||||||
|
auth_ctr = sysmo_usim_get_auth_counter(sim)
|
||||||
|
print "* Authentication Counter: %s\n" % auth_ctr
|
||||||
|
|
||||||
# Show current milenage parameters
|
# Show current milenage parameters
|
||||||
def sysmo_usim_show_milenage_params(sim):
|
def sysmo_usim_show_milenage_params(sim):
|
||||||
|
|
Loading…
Reference in New Issue