WIP Add full TUAK support
This commit is contained in:
parent
6de38540ee
commit
137baef6d8
|
@ -32,7 +32,8 @@ from common import *
|
|||
class Application(Common):
|
||||
|
||||
getopt_dump = False
|
||||
|
||||
getopt_show_tuak_cfg = False
|
||||
getopt_write_tuak_cfg = None
|
||||
|
||||
# Automatically executed by superclass
|
||||
def _banner(self):
|
||||
|
@ -46,11 +47,17 @@ class Application(Common):
|
|||
for opt, arg in opts:
|
||||
if opt in ("-d", "--dump"):
|
||||
self.getopt_dump = True
|
||||
|
||||
elif opt in ("-w", "--tuak-cfg"):
|
||||
self.getopt_show_tuak_cfg = True
|
||||
elif opt in ("-W", "--set-tuak-cfg"):
|
||||
self.getopt_write_tuak_cfg = arg.split(':', 3)
|
||||
|
||||
# Automatically executed by superclass when -h or --help is supplied as option
|
||||
def _helptext(self):
|
||||
print(" -d, --dump ..................... Dump propritary file contents")
|
||||
#TODO: add a help screen to explain what RMCK means
|
||||
print(" -w, --tuak-cfg ................. Show TUAK configuration")
|
||||
print(" -W, --set-tuak-cfg R:M:C:K ..... Set TUAK configuration")
|
||||
print("")
|
||||
print(" For Option -T, the following algorithms are valid:")
|
||||
print('\n'.join([' %d %s' % entry for entry in sysmo_isimsja5_algorithms]))
|
||||
|
@ -67,11 +74,15 @@ class Application(Common):
|
|||
|
||||
if self.getopt_dump:
|
||||
self.sim.dump()
|
||||
|
||||
elif self.getopt_show_tuak_cfg:
|
||||
self.sim.show_tuak_cfg()
|
||||
elif self.getopt_write_tuak_cfg:
|
||||
self.sim.write_tuak_cfg(self.getopt_write_tuak_cfg[0], self.getopt_write_tuak_cfg[1], \
|
||||
self.getopt_write_tuak_cfg[2], self.getopt_write_tuak_cfg[3])
|
||||
|
||||
def main(argv):
|
||||
|
||||
Application(argv, "d", ["dump"])
|
||||
Application(argv, "dwW:", ["dump"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -40,15 +40,15 @@ import math
|
|||
# |
|
||||
# +--[ADF_USIM]
|
||||
# | |
|
||||
# | +--[USIM_AUTH_KEY 0xAF20] (regular file)
|
||||
# | +--[EF_USIM_AUTH_KEY 0xAF20] (regular file)
|
||||
# | |
|
||||
# | +--[EF_USIM_AUTH_KEY_2G 0xAF22] (link to DF_SYSTEM/EF_SIM_AUTH_KEY) # <-- FIXME: is this still true?
|
||||
# | +--[EF_USIM_AUTH_KEY_2G 0xAF22] (link to DF_SYSTEM/EF_SIM_AUTH_KEY)
|
||||
# |
|
||||
# +--[ADF_ISIM]
|
||||
# |
|
||||
# +--[USIM_AUTH_KEY 0xAF20] (regular file)
|
||||
# +--[EF_ISIM_AUTH_KEY 0xAF20] (regular file)
|
||||
# |
|
||||
# +--[EF_USIM_AUTH_KEY_2G 0xAF22] (link to DF_SYSTEM/EF_SIM_AUTH_KEY) # <-- FIXME: is this still true?
|
||||
# +--[EF_ISIM_AUTH_KEY_2G 0xAF22] (link to DF_SYSTEM/EF_SIM_AUTH_KEY)
|
||||
#
|
||||
# Note: EF_MILENAGE_CFG and EF_USIM_SQN not yet listed here.
|
||||
|
||||
|
@ -104,6 +104,15 @@ sysmo_isimsjax_op_opc = [
|
|||
(False, 'OP'),
|
||||
]
|
||||
|
||||
sysmo_isimsja5_top_topc = [
|
||||
(True, 'TOPc'),
|
||||
(False, 'TOP'),
|
||||
]
|
||||
|
||||
res_sizes = [(0, "32"), (1, "64"), (2, "128"), (3, "256")]
|
||||
mac_sizes = [(0, "64"), (1, "128"), (2, "256")]
|
||||
ckik_sizes = [(0, "128"), (1, "256")]
|
||||
|
||||
class SYSMO_ISIMSJAX_ALGO_PARS_MILENAGE:
|
||||
use_opc = False
|
||||
sres_dev_func = 1
|
||||
|
@ -125,16 +134,16 @@ class SYSMO_ISIMSJAX_ALGO_PARS_MILENAGE:
|
|||
pfx = " "
|
||||
|
||||
if self.use_opc == True:
|
||||
dump += pfx + "Milenage: use OPc\n"
|
||||
dump += pfx + "use OPc\n"
|
||||
else:
|
||||
dump += pfx + "Milenage: use OP\n"
|
||||
dump += pfx + "use OP\n"
|
||||
|
||||
dump += pfx + "Milenage: use SRES deviation function " + str(self.sres_dev_func) + "\n"
|
||||
dump += pfx + "use SRES deviation function " + str(self.sres_dev_func) + "\n"
|
||||
|
||||
if self.four_byte_res:
|
||||
dump += pfx + "Milenage: Return 4 byte RES\n"
|
||||
dump += pfx + "Return 4 byte RES\n"
|
||||
else:
|
||||
dump += pfx + "Milenage: Return full 8 byte RES\n"
|
||||
dump += pfx + "Return full 8 byte RES\n"
|
||||
|
||||
return dump
|
||||
|
||||
|
@ -164,9 +173,9 @@ class SYSMO_ISIMSJAX_ALGO_PARS_SHA1AKA:
|
|||
pfx = " "
|
||||
|
||||
if self.four_byte_res:
|
||||
dump += pfx + "SHA1-AKA: Return 4 byte RES\n"
|
||||
dump += pfx + "Return 4 byte RES\n"
|
||||
else:
|
||||
dump += pfx + "SHA1-AKA: Return full 8 byte RES (default)\n"
|
||||
dump += pfx + "Return full 8 byte RES (default)\n"
|
||||
return dump
|
||||
|
||||
|
||||
|
@ -196,14 +205,14 @@ class SYSMO_ISIMSJAX_ALGO_PARS_XOR:
|
|||
dump = ""
|
||||
pfx = " "
|
||||
|
||||
dump += pfx + "XOR (3G): use SRES deviation function" + str(self.sres_dev_func) + "\n"
|
||||
dump += pfx + "use SRES deviation function" + str(self.sres_dev_func) + "\n"
|
||||
|
||||
if self.sixteen_byte_res:
|
||||
dump += pfx + "XOR (3G): Return extended 16 byte RES\n"
|
||||
dump += pfx + "Return extended 16 byte RES\n"
|
||||
elif self.four_byte_res:
|
||||
dump += pfx + "XOR (3G): Return 4 byte RES\n"
|
||||
dump += pfx + "Return 4 byte RES\n"
|
||||
else:
|
||||
dump += pfx + "XOR (3G): Return full 8 byte RES (default)\n"
|
||||
dump += pfx + "Return full 8 byte RES (default)\n"
|
||||
|
||||
return dump
|
||||
|
||||
|
@ -216,6 +225,50 @@ class SYSMO_ISIMSJAX_ALGO_PARS_XOR:
|
|||
return out
|
||||
|
||||
|
||||
class SYSMO_ISIMSJA5_ALGO_PARS_TUAK:
|
||||
use_topc = False
|
||||
sres_dev_func = 1
|
||||
use_256_bit_key = False
|
||||
|
||||
def __init__(self, content = None):
|
||||
if content == None:
|
||||
return
|
||||
|
||||
header = content[0]
|
||||
self.use_topc = bool((header >> 4) & 1)
|
||||
if (header >> 5) & 1:
|
||||
self.sres_dev_func = 2
|
||||
self.use_256_bit_key = bool((header >> 6) & 1)
|
||||
|
||||
|
||||
def __str__(self) -> str:
|
||||
dump = ""
|
||||
pfx = " "
|
||||
|
||||
if self.use_topc == True:
|
||||
dump += pfx + "use TOPc\n"
|
||||
else:
|
||||
dump += pfx + "use TOP\n"
|
||||
|
||||
dump += pfx + "use SRES deviation function " + str(self.sres_dev_func) + "\n"
|
||||
|
||||
if self.use_256_bit_key:
|
||||
dump += pfx + "256 bit key length\n"
|
||||
else:
|
||||
dump += pfx + "128 bit key length\n"
|
||||
|
||||
return dump
|
||||
|
||||
|
||||
def encode(self) -> int:
|
||||
out = 0x00
|
||||
if self.use_topc == True:
|
||||
out |= 1 << 4
|
||||
out |= ((self.sres_dev_func-1) & 1) << 5
|
||||
out |= ((self.use_256_bit_key) & 1) << 6
|
||||
return out
|
||||
|
||||
|
||||
class SYSMO_ISIMSJAX_FILE_EF_XSIM_AUTH_KEY:
|
||||
"""
|
||||
Superclass model that generates and parses the header byte of
|
||||
|
@ -239,6 +292,8 @@ class SYSMO_ISIMSJAX_FILE_EF_XSIM_AUTH_KEY:
|
|||
self.algo_pars = SYSMO_ISIMSJAX_ALGO_PARS_SHA1AKA(content)
|
||||
elif self.algo == SYSMO_ISIMSJA2_ALGO_XOR:
|
||||
self.algo_pars = SYSMO_ISIMSJAX_ALGO_PARS_XOR(content)
|
||||
elif self.algo == SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
self.algo_pars = SYSMO_ISIMSJA5_ALGO_PARS_TUAK(content)
|
||||
|
||||
|
||||
def __str__(self) -> str:
|
||||
|
@ -276,7 +331,7 @@ class SYSMO_ISIMSJAX_ALGO_KEY_COMP128:
|
|||
|
||||
dump = ""
|
||||
pfx = " "
|
||||
dump += pfx + "Ki: " + hexdump(self.ki) + "\n"
|
||||
dump += pfx + "Ki: " + hexdump(self.ki)
|
||||
|
||||
return dump
|
||||
|
||||
|
@ -311,6 +366,7 @@ class SYSMO_ISIMSJAX_ALGO_KEY_MILENAGE(SYSMO_ISIMSJAX_ALGO_KEY_COMP128):
|
|||
dump = ""
|
||||
pfx = " "
|
||||
dump += super().__str__()
|
||||
dump += "\n"
|
||||
dump += pfx + "OPc: " + hexdump(self.opc)
|
||||
|
||||
return dump
|
||||
|
@ -321,6 +377,66 @@ class SYSMO_ISIMSJAX_ALGO_KEY_MILENAGE(SYSMO_ISIMSJAX_ALGO_KEY_COMP128):
|
|||
return super().encode() + self.opc
|
||||
|
||||
|
||||
SYSMO_ISIMSJA5_TUAK_RES_SIZE_32_BIT = 0
|
||||
SYSMO_ISIMSJA5_TUAK_RES_SIZE_64_BIT = 1
|
||||
SYSMO_ISIMSJA5_TUAK_RES_SIZE_128_BIT = 2
|
||||
SYSMO_ISIMSJA5_TUAK_RES_SIZE_256_BIT = 3
|
||||
SYSMO_ISIMSJA5_TUAK_MAC_SIZE_64_BIT = 0
|
||||
SYSMO_ISIMSJA5_TUAK_MAC_SIZE_128_BIT = 1
|
||||
SYSMO_ISIMSJA5_TUAK_MAC_SIZE_256_BIT = 2
|
||||
|
||||
SYSMO_ISIMSJA5_TUAK_CKIK_SIZE_128_BIT = 0
|
||||
SYSMO_ISIMSJA5_TUAK_CKIK_SIZE_256_BIT = 1
|
||||
|
||||
class SYSMO_ISIMSJAX_ALGO_KEY_TUAK:
|
||||
|
||||
res_size = 0 #3 bit value
|
||||
mac_size = 0 #3 bit value
|
||||
ckik_size = 0 #1 bit value
|
||||
num_keccak = 0 #1 byte value
|
||||
topc = [0x00] * 32
|
||||
key = [0x00] * 32
|
||||
|
||||
def __init__(self, content = None):
|
||||
if content == None:
|
||||
return
|
||||
|
||||
self.res_size = int(content[1] & 7)
|
||||
self.mac_size = int((content[1] >> 3) & 7)
|
||||
self.ckik_size = bool((content[1] >> 6) & 1)
|
||||
|
||||
self.num_keccak = content[2]
|
||||
|
||||
self.topc = content[3:35]
|
||||
self.key = content[35:67]
|
||||
|
||||
def __str__(self) -> str:
|
||||
|
||||
dump = ""
|
||||
pfx = " "
|
||||
dump += pfx + "RES size: %s bit" % id_to_str(res_sizes, self.res_size) + "\n"
|
||||
dump += pfx + "MAC-A/MAC-S size: %s bit" % id_to_str(mac_sizes, self.mac_size) + "\n"
|
||||
dump += pfx + "Keccak iterations: %d" % self.num_keccak + "\n"
|
||||
dump += pfx + "TOPc: " + hexdump(self.topc) + "\n"
|
||||
#TODO: Keys may be 128 or 256 bits long. The key length is defined
|
||||
#in the header of the file, which means we cannot access this bit
|
||||
#from here but it would be nice to display the key in its correct
|
||||
#length though.
|
||||
dump += pfx + "Key: " + hexdump(self.key)
|
||||
return dump
|
||||
|
||||
|
||||
def encode(self) -> list:
|
||||
param_byte = self.res_size & 7
|
||||
param_byte |= (self.res_size & 7) << 3
|
||||
param_byte |= (self.ckik_size & 1) << 6
|
||||
out = [param_byte]
|
||||
out += [self.num_keccak]
|
||||
out += self.topc
|
||||
out += self.key
|
||||
return out
|
||||
|
||||
|
||||
class SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY(SYSMO_ISIMSJAX_FILE_EF_XSIM_AUTH_KEY):
|
||||
|
||||
algo_key = None
|
||||
|
@ -341,9 +457,10 @@ class SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY(SYSMO_ISIMSJAX_FILE_EF_XSIM_AUTH_KEY)
|
|||
elif self.algo == SYSMO_ISIMSJA2_ALGO_SHA1AKA:
|
||||
self.algo_key = SYSMO_ISIMSJAX_ALGO_KEY_SHA1AKA(content)
|
||||
elif self.algo == SYSMO_ISIMSJA2_ALGO_XOR or \
|
||||
self.algo_key == SYSMO_ISIMSJA5_ALGO_XOR_2G:
|
||||
self.algo == SYSMO_ISIMSJA5_ALGO_XOR_2G:
|
||||
self.algo_key = SYSMO_ISIMSJAX_ALGO_KEY_XOR(content)
|
||||
|
||||
elif self.algo == SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
self.algo_key = SYSMO_ISIMSJAX_ALGO_KEY_TUAK(content)
|
||||
|
||||
def __str__(self) -> str:
|
||||
|
||||
|
@ -357,10 +474,8 @@ class SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY(SYSMO_ISIMSJAX_FILE_EF_XSIM_AUTH_KEY)
|
|||
out = super().encode()
|
||||
if self.algo_key:
|
||||
out += self.algo_key.encode()
|
||||
#FIXME
|
||||
# else:
|
||||
# # See note in constructor above. An algo_key object must exist!
|
||||
# raise ValueError("key data encoding not supported for this algorithm!")
|
||||
else:
|
||||
raise ValueError("key data encoding not supported for selected algorithm!")
|
||||
return out
|
||||
|
||||
|
||||
|
@ -762,7 +877,7 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
|
||||
# Show current Ki value
|
||||
def show_ki_params(self):
|
||||
print("Reading Ki value...")
|
||||
print("Reading Key value...")
|
||||
self._init()
|
||||
|
||||
print(" * Reading...")
|
||||
|
@ -781,34 +896,48 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
else:
|
||||
ef_4g5g = None
|
||||
|
||||
print(" * Current Ki setting:")
|
||||
print(" * Current Key setting:")
|
||||
|
||||
if ef_2g.algo in sysmo_isimsjax_ki_algorithms:
|
||||
print(" 2g: Ki: " + hexdump(ef_2g.algo_key.ki))
|
||||
print(" 2g: Key: " + hexdump(ef_2g.algo_key.ki))
|
||||
elif ef_2g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
if not ef_2g.algo_pars.use_256_bit_key:
|
||||
print(" 2g: Key: " + hexdump(ef_2g.algo_key.key[0:16]))
|
||||
else:
|
||||
print(" 2g: Key: " + hexdump(ef_2g.algo_key.key))
|
||||
else:
|
||||
print(" * 2g: Ki not applicable for selected algorithm.")
|
||||
print(" * 2g: Key not applicable for selected algorithm.")
|
||||
|
||||
if ef_3g.algo in sysmo_isimsjax_ki_algorithms:
|
||||
print(" 3g: Ki: " + hexdump(ef_3g.algo_key.ki))
|
||||
print(" 3g: Key: " + hexdump(ef_3g.algo_key.ki))
|
||||
elif ef_3g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
if not ef_3g.algo_pars.use_256_bit_key:
|
||||
print(" 3g: Key: " + hexdump(ef_3g.algo_key.key[0:16]))
|
||||
else:
|
||||
print(" 3g: Key: " + hexdump(ef_3g.algo_key.key))
|
||||
else:
|
||||
print(" * 3g: Ki not applicable for selected algorithm.")
|
||||
print(" * 3g: Key not applicable for selected algorithm.")
|
||||
|
||||
if ef_4g5g.algo in sysmo_isimsjax_ki_algorithms:
|
||||
if ef_4g5g.algo is SYSMO_ISIMSJA2_ALGO_MILENAGE:
|
||||
print(" 4g5g: Ki: " + hexdump(ef_4g5g.algo_key.ki))
|
||||
print(" 4g5g: Key: " + hexdump(ef_4g5g.algo_key.ki))
|
||||
elif ef_4g5g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
if not ef_4g5g.algo_pars.use_256_bit_key:
|
||||
print(" 4g5g: Key: " + hexdump(ef_4g5g.algo_key.key[0:16]))
|
||||
else:
|
||||
print(" * 4g5g: Ki not applicable for selected algorithm.")
|
||||
print(" 4g5g: Key: " + hexdump(ef_4g5g.algo_key.key))
|
||||
else:
|
||||
print(" * 4g5g: Key not applicable for selected algorithm.")
|
||||
|
||||
print("")
|
||||
|
||||
|
||||
# Program new Ki value
|
||||
def write_ki_params(self, ki):
|
||||
print("Writing Ki value...")
|
||||
print("Writing Key value...")
|
||||
self._init()
|
||||
|
||||
print(" * New Ki setting:")
|
||||
print(" Ki: " + hexdump(ki))
|
||||
print(" * New Key setting:")
|
||||
print(" Key: " + hexdump(ki))
|
||||
|
||||
print(" * Programming...")
|
||||
|
||||
|
@ -818,8 +947,16 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
if ef.algo in sysmo_isimsjax_ki_algorithms:
|
||||
ef.algo_key.ki = ki
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" * 2g: Key programmed.")
|
||||
elif ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.key = ki
|
||||
ef.algo_pars.use_256_bit_key = False
|
||||
if len(ki) > 16:
|
||||
ef.algo_pars.use_256_bit_key = True
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" * 2g: Key programmed.")
|
||||
else:
|
||||
print(" * The selected 2g algorithm does not use a Ki, skipping...")
|
||||
print(" * 2g: Key not applicable for selected algorithm.")
|
||||
|
||||
self.__select_xsim_auth_key(isim = False, _2G = False)
|
||||
res = self._read_binary(self.sim.filelen)
|
||||
|
@ -827,8 +964,16 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
if ef.algo in sysmo_isimsjax_ki_algorithms:
|
||||
ef.algo_key.ki = ki
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" * 3g: Key programmed.")
|
||||
elif ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.key = ki
|
||||
ef.algo_pars.use_256_bit_key = False
|
||||
if len(ki) > 16:
|
||||
ef.algo_pars.use_256_bit_key = True
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" * 3g: Key programmed.")
|
||||
else:
|
||||
print(" * The selected 3g algorithm does not use a Ki, skipping...")
|
||||
print(" * 3g: Key not applicable for selected algorithm.")
|
||||
|
||||
if self.sim.has_isim:
|
||||
self.__select_xsim_auth_key(isim = True, _2G = False)
|
||||
|
@ -837,8 +982,17 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
if ef.algo in sysmo_isimsjax_ki_algorithms:
|
||||
ef.algo_key.ki = ki
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" * 4g5g: Key programmed.")
|
||||
elif ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.key = ki
|
||||
ef.algo_pars.use_256_bit_key = False
|
||||
if len(ki) > 16:
|
||||
ef.algo_pars.use_256_bit_key = True
|
||||
self.sim.update_binary(ef.encode())
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" * 4g5g: Key programmed.")
|
||||
else:
|
||||
print(" * The selected 3g4g algorithm does not use a Ki, skipping...")
|
||||
print(" * 4g5g: Key not applicable for selected algorithm.")
|
||||
|
||||
print("")
|
||||
|
||||
|
@ -950,19 +1104,28 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
if ef_2g.algo is SYSMO_ISIMSJA2_ALGO_MILENAGE:
|
||||
print(" 2g: %s: %s" % (id_to_str(sysmo_isimsjax_op_opc, ef_2g.algo_pars.use_opc), \
|
||||
hexdump(ef_2g.algo_key.opc)))
|
||||
elif ef_2g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
print(" 2g: %s: %s" % (id_to_str(sysmo_isimsja5_top_topc, ef_2g.algo_pars.use_topc), \
|
||||
hexdump(ef_2g.algo_key.topc)))
|
||||
else:
|
||||
print(" * 2g: OP/OPc not applicable for selected algorithm.")
|
||||
|
||||
if ef_3g.algo is SYSMO_ISIMSJA2_ALGO_MILENAGE:
|
||||
print(" 3g: %s: %s" % (id_to_str(sysmo_isimsjax_op_opc, ef_2g.algo_pars.use_opc), \
|
||||
print(" 3g: %s: %s" % (id_to_str(sysmo_isimsjax_op_opc, ef_3g.algo_pars.use_opc), \
|
||||
hexdump(ef_3g.algo_key.opc)))
|
||||
elif ef_3g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
print(" 3g: %s: %s" % (id_to_str(sysmo_isimsja5_top_topc, ef_3g.algo_pars.use_topc), \
|
||||
hexdump(ef_3g.algo_key.topc)))
|
||||
else:
|
||||
print(" * 3g: OP/OPc not applicable for selected algorithm.")
|
||||
|
||||
if ef_4g5g:
|
||||
if ef_4g5g.algo is SYSMO_ISIMSJA2_ALGO_MILENAGE:
|
||||
print(" 4g5g: %s: %s" % (id_to_str(sysmo_isimsjax_op_opc, ef_2g.algo_pars.use_opc), \
|
||||
print(" 4g5g: %s: %s" % (id_to_str(sysmo_isimsjax_op_opc, ef_4g5g.algo_pars.use_opc), \
|
||||
hexdump(ef_4g5g.algo_key.opc)))
|
||||
elif ef_4g5g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
print(" 4g5g: %s: %s" % (id_to_str(sysmo_isimsja5_top_topc, ef_4g5g.algo_pars.use_topc), \
|
||||
hexdump(ef_4g5g.algo_key.topc)))
|
||||
else:
|
||||
print(" * 4g5g: OP/OPc not applicable for selected algorithm.")
|
||||
|
||||
|
@ -992,8 +1155,14 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
ef.algo_key.opc = op
|
||||
ef.algo_pars.use_opc = bool(select)
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 2g %s programmed." % id_to_str(sysmo_isimsjax_op_opc, bool(select)));
|
||||
elif ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.topc = op
|
||||
ef.algo_pars.use_topc = bool(select)
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 2g %s programmed." % id_to_str(sysmo_isimsja5_top_topc, bool(select)));
|
||||
else:
|
||||
print(" 2G algorithm not configured for milenage, skipping...");
|
||||
print(" 2g OP/OPc not applicable for selected algorithm, skipping...")
|
||||
|
||||
self.__select_xsim_auth_key(isim = False, _2G = False)
|
||||
res = self._read_binary(self.sim.filelen)
|
||||
|
@ -1002,8 +1171,14 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
ef.algo_key.opc = op
|
||||
ef.algo_pars.use_opc = bool(select)
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 3g %s programmed." % id_to_str(sysmo_isimsjax_op_opc, bool(select)));
|
||||
elif ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.topc = op
|
||||
ef.algo_pars.use_topc = bool(select)
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 3g %s programmed." % id_to_str(sysmo_isimsja5_top_topc, bool(select)));
|
||||
else:
|
||||
print(" 3G algorithm not configured for milenage, skipping...");
|
||||
print(" 3g OP/OPc not applicable for selected algorithm, skipping...")
|
||||
|
||||
if self.sim.has_isim:
|
||||
self.__select_xsim_auth_key(isim = True, _2G = False)
|
||||
|
@ -1013,8 +1188,14 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
ef.algo_key.opc = op
|
||||
ef.algo_pars.use_opc = bool(select)
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 4g5g %s programmed." % id_to_str(sysmo_isimsjax_op_opc, bool(select)));
|
||||
elif ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.topc = op
|
||||
ef.algo_pars.use_topc = bool(select)
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 4g5g %s programmed." % id_to_str(sysmo_isimsja5_top_topc, bool(select)));
|
||||
else:
|
||||
print(" 4G/5G algorithm not configured for milenage, skipping...");
|
||||
print(" 4g/5g OP/OPc not applicable for selected algorithm, skipping...")
|
||||
|
||||
print("")
|
||||
|
||||
|
@ -1063,6 +1244,137 @@ class Sysmo_isim_sja2(Sysmo_usim):
|
|||
|
||||
print("")
|
||||
|
||||
def show_tuak_cfg(self):
|
||||
|
||||
print("Reading TUAK configuration...")
|
||||
self._init()
|
||||
|
||||
print(" * Reading...")
|
||||
self.__select_xsim_auth_key(isim = False, _2G = True)
|
||||
res = self._read_binary(self.sim.filelen)
|
||||
ef_2g = SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY(res.apdu)
|
||||
|
||||
self.__select_xsim_auth_key(isim = False, _2G = False)
|
||||
res = self._read_binary(self.sim.filelen)
|
||||
ef_3g = SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY(res.apdu)
|
||||
|
||||
if self.sim.has_isim:
|
||||
self.__select_xsim_auth_key(isim = True, _2G = False)
|
||||
res = self._read_binary(self.sim.filelen)
|
||||
ef_4g5g = SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY(res.apdu)
|
||||
else:
|
||||
ef_4g5g = None
|
||||
|
||||
print(" * Current TUAK configuration:")
|
||||
|
||||
if ef_2g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
print(" 2g: RES size: %s bit" % id_to_str(res_sizes, ef_2g.algo_key.res_size))
|
||||
print(" MAC-A/MAC-S size: %s bit" % id_to_str(mac_sizes, ef_2g.algo_key.mac_size))
|
||||
print(" CK/IK size: %s bit" % id_to_str(ckik_sizes, ef_2g.algo_key.ckik_size))
|
||||
print(" Keccak iterations: %d" % ef_2g.algo_key.num_keccak)
|
||||
else:
|
||||
print(" * 2g: TUAK configuration not applicable for selected algorithm.")
|
||||
|
||||
if ef_3g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
print(" 3g: RES size: %s bit" % id_to_str(res_sizes, ef_3g.algo_key.res_size))
|
||||
print(" MAC-A/MAC-S size: %s bit" % id_to_str(mac_sizes, ef_3g.algo_key.mac_size))
|
||||
print(" CK/IK size: %s bit" % id_to_str(ckik_sizes, ef_3g.algo_key.ckik_size))
|
||||
print(" Keccak iterations: %d" % ef_3g.algo_key.num_keccak)
|
||||
else:
|
||||
print(" * 3g: TUAK configuration not applicable for selected algorithm.")
|
||||
|
||||
if ef_4g5g:
|
||||
if ef_4g5g.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
print(" 4g5g: RES size: %s bit" % id_to_str(res_sizes, ef_4g5g.algo_key.res_size))
|
||||
print(" MAC-A/MAC-S size: %s bit" % id_to_str(mac_sizes, ef_4g5g.algo_key.mac_size))
|
||||
print(" CK/IK size: %s bit" % id_to_str(ckik_sizes, ef_4g5g.algo_key.ckik_size))
|
||||
print(" Keccak iterations: %d" % ef_4g5g.algo_key.num_keccak)
|
||||
else:
|
||||
print(" * 4g5g: TUAK configuration not applicable for selected algorithm.")
|
||||
|
||||
print("")
|
||||
|
||||
|
||||
def write_tuak_cfg(self, res_size_str:str, mac_size_str:str, ckik_size_str:str, num_keccak_str:str):
|
||||
|
||||
print("Writing TUAK configuration...")
|
||||
self._init()
|
||||
|
||||
print(" * New TUAK configuration:")
|
||||
|
||||
res_size = str_to_id(res_sizes, res_size_str, -1)
|
||||
if res_size < 0:
|
||||
print(" * Invalid TUAK configuration, RES-Size must be 32, 64, 128 or 256 bit!")
|
||||
print("")
|
||||
return
|
||||
|
||||
mac_size = str_to_id(mac_sizes, mac_size_str, -1)
|
||||
if mac_size < 0:
|
||||
print(" * Invalid TUAK configuration, MAC-Size must be 64, 128 or 256 bit!")
|
||||
print("")
|
||||
return
|
||||
|
||||
ckik_size = str_to_id(ckik_sizes, ckik_size_str, -1)
|
||||
if ckik_size < 0:
|
||||
print(" * Invalid TUAK configuration, MAC-Size must be 128 or 256 bit!")
|
||||
print("")
|
||||
return
|
||||
|
||||
num_keccak = int(num_keccak_str)
|
||||
if num_keccak > 255:
|
||||
print(" * Invalid TUAK configuration, number of KECCAK iterations must not exceed 256!")
|
||||
print("")
|
||||
return
|
||||
|
||||
print(" RES size: %s bit" % id_to_str(res_sizes, res_size))
|
||||
print(" MAC-A/MAC-S size: %s bit" % id_to_str(mac_sizes, mac_size))
|
||||
print(" CK/IK size: %s bit" % id_to_str(ckik_sizes, ckik_size))
|
||||
print(" Keccak iterations: %d" % num_keccak)
|
||||
|
||||
print(" * Programming...")
|
||||
|
||||
self.__select_xsim_auth_key(isim = False, _2G = True)
|
||||
res = self._read_binary(self.sim.filelen)
|
||||
ef = SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY_2G(res.apdu)
|
||||
if ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.res_size = res_size
|
||||
ef.algo_key.mac_size = mac_size
|
||||
ef.algo_key.ckik_size = ckik_size
|
||||
ef.algo_key.num_keccak = num_keccak
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 2g TUAK configuration programmed.");
|
||||
else:
|
||||
print(" 2g TUAK configuration not applicable for selected algorithm, skipping...")
|
||||
|
||||
self.__select_xsim_auth_key(isim = False, _2G = False)
|
||||
res = self._read_binary(self.sim.filelen)
|
||||
ef = SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY(res.apdu)
|
||||
if ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.res_size = res_size
|
||||
ef.algo_key.mac_size = mac_size
|
||||
ef.algo_key.ckik_size = ckik_size
|
||||
ef.algo_key.num_keccak = num_keccak
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 3g TUAK configuration programmed.");
|
||||
else:
|
||||
print(" 3g TUAK configuration not applicable for selected algorithm, skipping...")
|
||||
|
||||
if self.sim.has_isim:
|
||||
self.__select_xsim_auth_key(isim = True, _2G = False)
|
||||
res = self._read_binary(self.sim.filelen)
|
||||
ef = SYSMO_ISIMSJAX_FILE_EF_USIM_AUTH_KEY(res.apdu)
|
||||
if ef.algo is SYSMO_ISIMSJA5_ALGO_TUAK:
|
||||
ef.algo_key.res_size = res_size
|
||||
ef.algo_key.mac_size = mac_size
|
||||
ef.algo_key.ckik_size = ckik_size
|
||||
ef.algo_key.num_keccak = num_keccak
|
||||
self.sim.update_binary(ef.encode())
|
||||
print(" 4g5g TUAK configuration programmed.");
|
||||
else:
|
||||
print(" 4g5g TUAK configuration not applicable for selected algorithm, skipping...")
|
||||
|
||||
print("")
|
||||
|
||||
|
||||
class Sysmo_isim_sja5(Sysmo_isim_sja2):
|
||||
algorithms = sysmo_isimsja5_algorithms
|
||||
|
|
|
@ -42,6 +42,9 @@ Writing OPc value...
|
|||
* New OPc setting:
|
||||
OPc: 000102030405060708090a0b0c0d0e0f
|
||||
* Programming...
|
||||
2g OPc programmed.
|
||||
3g OPc programmed.
|
||||
4g5g OPc programmed.
|
||||
|
||||
Done!
|
||||
sysmoISIM-SJA5 parameterization tool
|
||||
|
@ -88,6 +91,9 @@ Writing OP value...
|
|||
* New OPc setting:
|
||||
OP: 840337c3d45397ce8ea8609ffdc47224
|
||||
* Programming...
|
||||
2g OP programmed.
|
||||
3g OP programmed.
|
||||
4g5g OP programmed.
|
||||
|
||||
Done!
|
||||
sysmoISIM-SJA5 parameterization tool
|
||||
|
|
|
@ -13,11 +13,14 @@ Authenticating...
|
|||
* Authentication successful
|
||||
* Remaining attempts: 3
|
||||
|
||||
Writing Ki value...
|
||||
Writing Key value...
|
||||
* Initalizing...
|
||||
* New Ki setting:
|
||||
Ki: a0b1c2d3e4f5061728394a5b6c7d8e9f
|
||||
* New Key setting:
|
||||
Key: a0b1c2d3e4f5061728394a5b6c7d8e9f
|
||||
* Programming...
|
||||
* 2g: Key programmed.
|
||||
* 3g: Key programmed.
|
||||
* 4g5g: Key programmed.
|
||||
|
||||
Done!
|
||||
sysmoISIM-SJA5 parameterization tool
|
||||
|
@ -35,13 +38,13 @@ Authenticating...
|
|||
* Authentication successful
|
||||
* Remaining attempts: 3
|
||||
|
||||
Reading Ki value...
|
||||
Reading Key value...
|
||||
* Initalizing...
|
||||
* Reading...
|
||||
* Current Ki setting:
|
||||
2g: Ki: a0b1c2d3e4f5061728394a5b6c7d8e9f
|
||||
3g: Ki: a0b1c2d3e4f5061728394a5b6c7d8e9f
|
||||
4g5g: Ki: a0b1c2d3e4f5061728394a5b6c7d8e9f
|
||||
* Current Key setting:
|
||||
2g: Key: a0b1c2d3e4f5061728394a5b6c7d8e9f
|
||||
3g: Key: a0b1c2d3e4f5061728394a5b6c7d8e9f
|
||||
4g5g: Key: a0b1c2d3e4f5061728394a5b6c7d8e9f
|
||||
|
||||
Done!
|
||||
sysmoISIM-SJA5 parameterization tool
|
||||
|
@ -59,11 +62,14 @@ Authenticating...
|
|||
* Authentication successful
|
||||
* Remaining attempts: 3
|
||||
|
||||
Writing Ki value...
|
||||
Writing Key value...
|
||||
* Initalizing...
|
||||
* New Ki setting:
|
||||
Ki: d7882eae7cd14f06108c55f8e5cffe93
|
||||
* New Key setting:
|
||||
Key: d7882eae7cd14f06108c55f8e5cffe93
|
||||
* Programming...
|
||||
* 2g: Key programmed.
|
||||
* 3g: Key programmed.
|
||||
* 4g5g: Key programmed.
|
||||
|
||||
Done!
|
||||
sysmoISIM-SJA5 parameterization tool
|
||||
|
@ -81,12 +87,12 @@ Authenticating...
|
|||
* Authentication successful
|
||||
* Remaining attempts: 3
|
||||
|
||||
Reading Ki value...
|
||||
Reading Key value...
|
||||
* Initalizing...
|
||||
* Reading...
|
||||
* Current Ki setting:
|
||||
2g: Ki: d7882eae7cd14f06108c55f8e5cffe93
|
||||
3g: Ki: d7882eae7cd14f06108c55f8e5cffe93
|
||||
4g5g: Ki: d7882eae7cd14f06108c55f8e5cffe93
|
||||
* Current Key setting:
|
||||
2g: Key: d7882eae7cd14f06108c55f8e5cffe93
|
||||
3g: Key: d7882eae7cd14f06108c55f8e5cffe93
|
||||
4g5g: Key: d7882eae7cd14f06108c55f8e5cffe93
|
||||
|
||||
Done!
|
||||
|
|
7
utils.py
7
utils.py
|
@ -100,10 +100,13 @@ def id_to_str(table, nr):
|
|||
|
||||
|
||||
# Convert a string back to its ID by looking it up in a given table
|
||||
def str_to_id(table, string):
|
||||
def str_to_id(table, string, safe_default = None):
|
||||
dict_by_name = dict([(name.upper(), nr) for nr, name in table])
|
||||
id = dict_by_name.get(string.upper())
|
||||
|
||||
if id is None:
|
||||
raise ValueError('identifier (\"%s\") not in table %s' % (string, str(table)))
|
||||
if safe_default != None:
|
||||
return safe_default
|
||||
else:
|
||||
raise ValueError('identifier (\"%s\") not in table %s' % (string, str(table)))
|
||||
return id
|
||||
|
|
Loading…
Reference in New Issue