WIP Add full TUAK support

This commit is contained in:
Philipp Maier 2023-06-13 19:51:32 +02:00
parent 6de38540ee
commit 137baef6d8
5 changed files with 402 additions and 64 deletions

View File

@ -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__":

View File

@ -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

View File

@ -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

View File

@ -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!

View File

@ -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