Tool to (re)configure the sysmoUSIM and sysmoISIM cards
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

857 lines
25 KiB

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. Gadgets to modify SYSMO USIM SJA2 parameters
  5. (C) 2017 by Sysmocom s.f.m.c. GmbH
  6. All Rights Reserved
  7. Author: Philipp Maier
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. import sys
  20. from utils import *
  21. from sysmo_usim import *
  22. import math
  23. # Partial File tree:
  24. # The following tree is incomplete, it just contains the propritary files we
  25. # need to perform the tasks implemented below:
  26. #
  27. # [MF 0x3F00]
  28. # |
  29. # +--[DF_SYSTEM 0xA515]
  30. # | |
  31. # | +--[EF_SIM_AUTH_KEY 0x6F20] (regular file)
  32. # |
  33. # +--[ADF_USIM]
  34. # | |
  35. # | +--[USIM_AUTH_KEY 0xAF20] (regular file)
  36. # | |
  37. # | +--[EF_USIM_AUTH_KEY_2G 0xAF22] (link to DF_SYSTEM/EF_SIM_AUTH_KEY)
  38. # |
  39. # +--[ADF_ISIM]
  40. # |
  41. # +--[USIM_AUTH_KEY 0xAF20] (regular file)
  42. # |
  43. # +--[EF_USIM_AUTH_KEY_2G 0xAF22] (link to DF_SYSTEM/EF_SIM_AUTH_KEY)
  44. #
  45. # Note: EF_MILENAGE_CFG and EF_USIM_SQN not yet listed here.
  46. # Propritary files
  47. SYSMO_ISIMSJA2_DF_SYSTEM = [0xA5, 0x15]
  48. SYSMO_ISIMSJA2_EF_SIM_AUTH_KEY = [0x6F, 0x20] # DF_SYSTEM
  49. SYSMO_ISIMSJA2_EF_USIM_AUTH_KEY = [0xAF, 0x20] # ADF.USIM
  50. SYSMO_ISIMSJA2_EF_USIM_AUTH_KEY_2G = [0xAF, 0x22] # ADF.USIM
  51. SYSMO_ISIMSJA2_EF_USIM_AUTH_KEY_GBA = [0xAF, 0x23] # ADF.USIM
  52. SYSMO_ISIMSJA2_EF_MILENAGE_CFG = [0xAF, 0x21] # ADF.USIM
  53. SYSMO_ISIMSJA2_EF_USIM_SQN = [0xAF, 0x30] # ADF.USIM
  54. SYSMO_ISIMSJA2_EF_GBA_SK = [0xAF, 0x31] # ADF.USIM
  55. SYSMO_ISIMSJA2_EF_GBA_REC_LIST = [0xAF, 0x32] # ADF.USIM
  56. SYSMO_ISIMSJA2_EF_GBA_INT_KEY = [0xAF, 0x32] # ADF.USIM
  57. # Authentication algorithms
  58. SYSMO_ISIMSJA2_ALGO_COMP12V1 = 0x01
  59. SYSMO_ISIMSJA2_ALGO_COMP12V2 = 0x02
  60. SYSMO_ISIMSJA2_ALGO_COMP12V3 = 0x03
  61. SYSMO_ISIMSJA2_ALGO_MILENAGE = 0x04
  62. SYSMO_ISIMSJA2_ALGO_SHA1AKA = 0x05
  63. SYSMO_ISIMSJA2_ALGO_XOR = 0x0F
  64. sysmo_isimsja2_algorithms = (
  65. (SYSMO_ISIMSJA2_ALGO_COMP12V1, 'COMP128v1'),
  66. (SYSMO_ISIMSJA2_ALGO_COMP12V2, 'COMP128v2'),
  67. (SYSMO_ISIMSJA2_ALGO_COMP12V3, 'XOR-2G'),
  68. (SYSMO_ISIMSJA2_ALGO_MILENAGE, 'MILENAGE'),
  69. (SYSMO_ISIMSJA2_ALGO_SHA1AKA , 'SHA1-AKA'),
  70. (SYSMO_ISIMSJA2_ALGO_XOR, 'XOR'),
  71. )
  72. class SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY:
  73. """
  74. Superclass model that generates that handles the header byte of
  75. SYSMO_ISIMSJA2_EF_USIM_AUTH_KEY, SYSMO_ISIMSJA2_EF_USIM_AUTH_KEY_2G
  76. and SYSMO_ISIMSJA2_EF_USIM_AUTH_KEY_GBA.
  77. """
  78. algo = SYSMO_ISIMSJA2_ALGO_COMP12V1
  79. use_opc = False
  80. sres_dev_func = 1
  81. def __init__(self, content = None):
  82. if content == None:
  83. return
  84. header = content[0]
  85. self.algo = header & 0x0F
  86. self.use_opc = bool((header >> 4) & 1)
  87. if (header >> 5) & 1:
  88. self.sres_dev_func = 2
  89. else:
  90. self.sres_dev_func = 1
  91. def __str__(self):
  92. dump = ""
  93. pfx = " "
  94. dump += pfx + "Algorithm: "
  95. dump += id_to_str(sysmo_isimsja2_algorithms, self.algo)
  96. dump += "\n"
  97. if self.use_opc == True:
  98. dump += pfx + "Milenage: use OPc\n"
  99. else:
  100. dump += pfx + "Milenage: use OP\n"
  101. dump += pfx + "Milenage: use SRES deviation function " + str(self.sres_dev_func) + "\n"
  102. return dump
  103. def encode(self):
  104. out = [0x00]
  105. out[0] = self.algo & 0x0F
  106. if self.use_opc == True:
  107. out[0] |= 1 << 4
  108. out[0] |= ((self.sres_dev_func-1) & 1) << 5
  109. return out
  110. class SYSMO_ISIMSJA2_FILE_EF_SIM_AUTH_KEY(SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY):
  111. key = [0xAA] * 16
  112. opc = [0xBB] * 16
  113. def __init__(self, content = None):
  114. if content == None:
  115. return
  116. SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY.__init__(self, content)
  117. self.key = content[1:17]
  118. self.opc = content[17:33]
  119. def __str__(self):
  120. dump = ""
  121. pfx = " "
  122. dump += SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY.__str__(self)
  123. if self.algo == SYSMO_ISIMSJA2_ALGO_MILENAGE:
  124. dump += pfx + "Key: " + hexdump(self.key) + "\n"
  125. dump += pfx + "OPc: " + hexdump(self.opc)
  126. elif self.algo == SYSMO_ISIMSJA2_ALGO_XOR:
  127. dump += pfx + "Key: " + hexdump(self.key) + "\n"
  128. dump += pfx + "OPc: " + hexdump(self.opc)
  129. elif self.algo == SYSMO_ISIMSJA2_ALGO_SHA1AKA:
  130. dump += pfx + "Root key: " + hexdump(self.key) + "\n"
  131. dump += pfx + "OPc: " + hexdump(self.opc) + " (unused)"
  132. else:
  133. dump += pfx + "Key: " + hexdump(self.key) + "\n"
  134. dump += pfx + "OPc: " + hexdump(self.opc) + " (unused)"
  135. return dump
  136. def encode(self):
  137. out = SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY.encode(self)
  138. out += self.key + self.opc
  139. return out
  140. class SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY):
  141. full_res = True # Return full 8-byte RES or first 4 bytes only
  142. ext_res = False # Return 16 byte RES (ignores full_res, only valid with 3G XOR)
  143. key = [0x00] * 16
  144. opc = [0x00] * 16 # Only for Milenage
  145. def __init__(self, content = None):
  146. if content == None:
  147. return
  148. SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY.__init__(self, content)
  149. header = content[0]
  150. self.full_res = bool((header >> 6) & 1)
  151. self.ext_res = bool((header >> 7) & 1)
  152. self.key = content[1:17]
  153. if len(content) > 17:
  154. self.opc = content[17:33]
  155. def __str__(self):
  156. dump = ""
  157. pfx = " "
  158. dump += SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY.__str__(self)
  159. if self.full_res == True and self.ext_res == False:
  160. dump += pfx + "3G: Return full 8-byte RES\n"
  161. elif self.full_res == False and self.ext_res == False:
  162. dump += pfx + "3G: Return first four bytes of RES\n"
  163. elif self.ext_res == True:
  164. dump += pfx + "3G: Return 16-byte RES (XOR 3G only)\n"
  165. else:
  166. dump += pfx + "(invalid RES length setting)"
  167. if self.algo != SYSMO_ISIMSJA2_ALGO_XOR and self.ext_res:
  168. dump += pfx + "Warning: 16-byte RES is only valid with XOR 3G!\n"
  169. if self.algo == SYSMO_ISIMSJA2_ALGO_MILENAGE:
  170. dump += pfx + "Key: " + hexdump(self.key) + "\n"
  171. dump += pfx + "OPc: " + hexdump(self.opc)
  172. elif self.algo == SYSMO_ISIMSJA2_ALGO_XOR:
  173. dump += pfx + "Key: " + hexdump(self.key) + "\n"
  174. dump += pfx + "OPc: " + hexdump(self.opc)
  175. elif self.algo == SYSMO_ISIMSJA2_ALGO_SHA1AKA:
  176. dump += pfx + "Root key: " + hexdump(self.key) + "\n"
  177. dump += pfx + "OPc: " + hexdump(self.opc) + " (unused)"
  178. else:
  179. dump += pfx + "Key: " + hexdump(self.key) + "\n"
  180. dump += pfx + "OPc: " + hexdump(self.opc) + " (unused)"
  181. return dump
  182. def encode(self):
  183. out = SYSMO_ISIMSJA2_FILE_EF_XSIM_AUTH_KEY.encode(self)
  184. if self.full_res == True:
  185. out[0] |= 1 << 6
  186. if self.ext_res == True:
  187. out[0] |= 1 << 7
  188. out += self.key
  189. # Note: Normally an OPc is only used with milenage, but lets
  190. # write the value anyway, even if it is not used.
  191. out += self.opc
  192. return out
  193. # EF_USIM_AUTH_KEY_2G and EF_USIM_AUTH_KEY_GBA have the same layout as
  194. # EF_USIM_AUTH_KEY, so there is nothing to specialize other than the class name
  195. class SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_2G(SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY):
  196. pass
  197. class SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_GBA(SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY):
  198. pass
  199. class SYSMO_ISIMSJA2_FILE_EF_MILENAGE_CFG:
  200. R1 = 0x40
  201. R2 = 0x00
  202. R3 = 0x20
  203. R4 = 0x40
  204. R5 = 0x60
  205. C1 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  206. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  207. C2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  208. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]
  209. C3 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  210. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02]
  211. C4 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  212. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04]
  213. C5 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  214. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08]
  215. def __init__(self, content = None):
  216. if content == None:
  217. return
  218. if len(content) != 85:
  219. return
  220. self.R1 = content[0]
  221. self.R2 = content[1]
  222. self.R3 = content[2]
  223. self.R4 = content[3]
  224. self.R5 = content[4]
  225. self.C1 = content[5:5+16]
  226. self.C2 = content[21:37]
  227. self.C3 = content[37:53]
  228. self.C4 = content[53:69]
  229. self.C5 = content[69:85]
  230. def __str__(self):
  231. dump = " R1: " + str(hex(self.R1)) + "\n"
  232. dump += " R2: " + str(hex(self.R2)) + "\n"
  233. dump += " R3: " + str(hex(self.R3)) + "\n"
  234. dump += " R4: " + str(hex(self.R4)) + "\n"
  235. dump += " R5: " + str(hex(self.R5)) + "\n"
  236. dump += " C1: " + hexdump(self.C1) + "\n"
  237. dump += " C2: " + hexdump(self.C2) + "\n"
  238. dump += " C3: " + hexdump(self.C3) + "\n"
  239. dump += " C4: " + hexdump(self.C4) + "\n"
  240. dump += " C5: " + hexdump(self.C5)
  241. return dump
  242. def encode(self):
  243. out = [self.R1, self.R2, self.R3, self.R4, self.R5]
  244. out += self.C1 + self.C2 + self.C3 + self.C4 + self.C5
  245. return out
  246. class SYSMO_ISIMSJA2_FILE_EF_USIM_SQN:
  247. # Flag1:
  248. ind_size_bits = 5 # speficy file length by 2^ind_len
  249. sqn_check_enabled = True # perform SQN checks below
  250. sqn_age_limit_enabled = False # perform age limit check: (SQNms-SQN) <= AGE_LIMIT)
  251. sqn_max_delta_enabled = True # perform delta max check: (SWN-SQNms) <= DELTA MAX)
  252. sqn_check_skip_first = True # accept any SQN on the first authentication
  253. # Flag2:
  254. conceal_autn = True # Conceal the value of AUTN
  255. conceal_auts = True # Conceal the value of AUTS
  256. no_amf_clear = False # Do not clear AMF when computing MAC-S
  257. # Data:
  258. max_delta = 2**28 << ind_size_bits
  259. age_limit = 2**28 << ind_size_bits
  260. freshness_data = [0x00] * (6*2**ind_size_bits) # initalize to zero
  261. def __init__(self, content = None):
  262. if content == None:
  263. return
  264. # Check if we have at least the header
  265. if len(content) <= 2:
  266. raise ValueError("unexpected length of %u bytes", len(content))
  267. flag1 = content[0]
  268. self.ind_size_bits = flag1 & 0xf
  269. # The parameter ind_size_bits is not user configurable,
  270. # its a fixed configuration that is specific to the
  271. # card profile and it can be determined by looking at the
  272. # file length (length of the freshness data). If we find
  273. # an ind_size_bits that is intconstant to the file length,
  274. # we automatically set the value to the correct length
  275. ind_size_bits_calculated = int(math.log((len(content) - 14) / 6, 2))
  276. if ind_size_bits_calculated != self.ind_size_bits:
  277. print(" Warning: SQN Parameter ind_size_bits is set to " + str(self.ind_size_bits) + ", resetting it to " + str(ind_size_bits_calculated) + "!")
  278. self.ind_size_bits = ind_size_bits_calculated
  279. self.reset() #ensure freshness data is correctly reset
  280. self.sqn_check_enabled = bool((flag1 >> 4) & 1)
  281. self.sqn_age_limit_enabled = bool((flag1 >> 5) & 1)
  282. self.sqn_max_delta_enabled = bool((flag1 >> 6) & 1)
  283. self.sqn_check_skip_first = bool((flag1 >> 7) & 1)
  284. flag2 = content[1]
  285. self.conceal_autn = bool(flag2 & 1)
  286. self.conceal_auts = bool((flag2 >> 1) & 1)
  287. self.no_amf_clear = bool((flag2 >> 2) & 1)
  288. # Check if the data body is complete
  289. if len(content) < 14+(6*2**self.ind_size_bits):
  290. raise ValueError("unexpected length of %u bytes" % len(content))
  291. self.max_delta = list_to_int(content[2:8])
  292. self.age_limit = list_to_int(content[8:14])
  293. self.freshness_data = content[15:(6*2**self.ind_size_bits)]
  294. def __str__(self):
  295. pfx = " "
  296. dump = ""
  297. dump += "%sIND (bits): %u\n" % (pfx, self.ind_size_bits)
  298. if self.sqn_check_enabled:
  299. dump += "%sSQN Check enabled\n" % pfx
  300. else:
  301. dump += "%sSQN Check disabled\n" % pfx
  302. if self.sqn_age_limit_enabled:
  303. dump += "%sSQN Age Limit enabled\n" % pfx
  304. else:
  305. dump += "%sSQN Age Limit disabled\n" % pfx
  306. if self.sqn_max_delta_enabled:
  307. dump += "%sSQN Max Delta enabled\n" % pfx
  308. else:
  309. dump += "%sSQN Max Delta disabled\n" % pfx
  310. if self.sqn_check_skip_first:
  311. dump += "%sSQN Skip first enabled\n" % pfx
  312. else:
  313. dump += "%sSQN Skip first disabled\n" % pfx
  314. if self.conceal_autn:
  315. dump += "%sSQN Conceal AUTN enabled\n" % pfx
  316. else:
  317. dump += "%sSQN Conceal AUTN disabled\n" % pfx
  318. if self.conceal_auts:
  319. dump += "%sSQN Conceal AUTS enabled\n" % pfx
  320. else:
  321. dump += "%sSQN Conceal AUTS disabled\n" % pfx
  322. if self.no_amf_clear:
  323. dump += "%sSQN No AMF clear enabled\n" % pfx
  324. else:
  325. dump += "%sSQN No AMF clear disabled\n" % pfx
  326. dump += "%sMax Delta: %u\n" % (pfx, self.max_delta)
  327. dump += "%sAge Limit: %u\n" % (pfx, self.age_limit)
  328. dump += pfx + "Freshness Data:\n" + hexdump(self.freshness_data, True)
  329. return dump
  330. def encode(self):
  331. out = [0x00, 0x00]
  332. # Flag1:
  333. out[0] = self.ind_size_bits & 0x0f
  334. if self.sqn_check_enabled:
  335. out[0] |= 1 << 4
  336. if self.sqn_age_limit_enabled:
  337. out[0] |= 1 << 5
  338. if self.sqn_max_delta_enabled:
  339. out[0] |= 1 << 6
  340. if self.sqn_check_skip_first:
  341. out[0] |= 1 << 7
  342. # Flag2:
  343. if self.conceal_autn:
  344. out[1] |= 1 << 0
  345. if self.conceal_auts:
  346. out[1] |= 1 << 1
  347. if self.no_amf_clear:
  348. out[1] |= 1 << 2
  349. # Data:
  350. out += int_to_list(self.max_delta, 6)
  351. out += int_to_list(self.age_limit, 6)
  352. out += self.freshness_data
  353. return out
  354. def reset(self):
  355. self.freshness_data = [0x00] * (6*2**self.ind_size_bits)
  356. class Sysmo_isim_sja2(Sysmo_usim):
  357. def __init__(self):
  358. card_detected = False
  359. # Try card model #1
  360. try:
  361. atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9"
  362. print("Trying to find card with ATR: " + atr)
  363. Sysmo_usim.__init__(self, atr)
  364. card_detected = True
  365. except:
  366. print(" * Card not detected!")
  367. if card_detected == True:
  368. return
  369. # Try card model #2
  370. try:
  371. atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 31 33 02 51 B2"
  372. print("Trying to find card with ATR: " + atr)
  373. Sysmo_usim.__init__(self, atr)
  374. card_detected = True
  375. except:
  376. print(" * Card not detected!")
  377. if card_detected == True:
  378. return
  379. # Try card model #3 (sysmoTSIM)
  380. try:
  381. atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 52 75 31 04 51 D5"
  382. print("Trying to find card with ATR: " + atr)
  383. Sysmo_usim.__init__(self, atr)
  384. card_detected = True
  385. except:
  386. print(" * Card not detected!")
  387. if card_detected == True:
  388. return
  389. # Exit when we are not able to detect the card
  390. if card_detected != True:
  391. sys.exit(1)
  392. # Show current milenage parameters
  393. def show_milenage_params(self):
  394. print("Reading Milenage parameters...")
  395. self._init()
  396. print(" * Reading...")
  397. self.sim.card.SELECT_ADF_USIM()
  398. self.sim.select(SYSMO_ISIMSJA2_EF_MILENAGE_CFG)
  399. res = self._read_binary(85)
  400. ef = SYSMO_ISIMSJA2_FILE_EF_MILENAGE_CFG(res.apdu)
  401. print(" * Current Milenage Parameters:")
  402. print(str(ef))
  403. print("")
  404. # Write new milenage parameters
  405. def write_milenage_params(self, params):
  406. print("Programming Milenage parameters...")
  407. if (len(params) < 85):
  408. print("Error: Short milenage parameters!")
  409. return
  410. params_swapped = params[80:85] + params[0:80]
  411. self._init()
  412. print(" * New Milenage Parameters for (EF.MILENAGE_CFG):")
  413. ef_milenage_cfg = SYSMO_ISIMSJA2_FILE_EF_MILENAGE_CFG(params_swapped)
  414. print(str(ef_milenage_cfg))
  415. print(" * Programming...")
  416. # Note: The milenage configuration file in ADF_USIM and
  417. # ADF_ISIM are linked, however we write to both locations,
  418. # just to be sure.
  419. self.sim.card.SELECT_ADF_USIM()
  420. self.sim.select(SYSMO_ISIMSJA2_EF_MILENAGE_CFG)
  421. self.sim.update_binary(ef_milenage_cfg.encode())
  422. if self.sim.has_isim:
  423. self.sim.card.SELECT_ADF_ISIM()
  424. self.sim.select(SYSMO_ISIMSJA2_EF_MILENAGE_CFG)
  425. self.sim.update_binary(ef_milenage_cfg.encode())
  426. print("")
  427. # Select DF_SYSTEM/EF_SIM_AUTH_KEY
  428. def __select_ef_sim_auth_key(self):
  429. self.sim.select(GSM_SIM_MF)
  430. self.sim.select(SYSMO_ISIMSJA2_DF_SYSTEM)
  431. self.sim.select(SYSMO_ISIMSJA2_EF_SIM_AUTH_KEY)
  432. # Authentication keys exist in various different files, which are
  433. # similar, thie method simplifies the selection of those files
  434. def __select_xsim_auth_key(self, isim = False, _2G = False):
  435. self.sim.select(GSM_SIM_MF)
  436. if isim:
  437. self.sim.card.SELECT_ADF_ISIM()
  438. else:
  439. self.sim.card.SELECT_ADF_USIM()
  440. if _2G:
  441. self.sim.select(SYSMO_ISIMSJA2_EF_USIM_AUTH_KEY_2G)
  442. else:
  443. self.sim.select(SYSMO_ISIMSJA2_EF_USIM_AUTH_KEY)
  444. # In the SJA2 model the key material and the algorithm configuration
  445. # is distributed over multiple files, which may also have redundant
  446. # contents. Files can also be hard linked to other files so that
  447. # changes in one file may appear in another file as well. The dump
  448. # method provides an overview of contents of all files at once in
  449. # order to help debugging problems
  450. def dump(self):
  451. print("Reading propritary files...")
  452. self._init()
  453. # DF_SYSTEM/EF_SIM_AUTH_KEY:
  454. self.__select_ef_sim_auth_key()
  455. res = self._read_binary(self.sim.filelen)
  456. print(" * DF_SYSTEM/EF_SIM_AUTH_KEY:")
  457. print(SYSMO_ISIMSJA2_FILE_EF_SIM_AUTH_KEY(res.apdu))
  458. # ADF_USIM/EF_USIM_AUTH_KEY_2G:
  459. self.__select_xsim_auth_key(isim = False, _2G = True)
  460. res = self._read_binary(self.sim.filelen)
  461. print(" * ADF_USIM/EF_USIM_AUTH_KEY_2G:")
  462. print(SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_2G(res.apdu))
  463. if self.sim.has_isim:
  464. # ADF_ISIM/EF_ISIM_AUTH_KEY_2G:
  465. self.__select_xsim_auth_key(isim = True, _2G = True)
  466. res = self._read_binary(self.sim.filelen)
  467. print(" * ADF_ISIM/EF_ISIM_AUTH_KEY_2G:")
  468. print(SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_2G(res.apdu))
  469. # ADF_USIM/EF_USIM_AUTH_KEY:
  470. self.__select_xsim_auth_key(isim = False, _2G = False)
  471. res = self._read_binary(self.sim.filelen)
  472. print(" * ADF_USIM/EF_USIM_AUTH_KEY:")
  473. print(SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu))
  474. if self.sim.has_isim:
  475. # ADF_ISIM/EF_ISIM_AUTH_KEY:
  476. self.__select_xsim_auth_key(isim = True, _2G = False)
  477. res = self._read_binary(self.sim.filelen)
  478. print(" * ADF_ISIM/EF_ISIM_AUTH_KEY:")
  479. print(SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu))
  480. # ADF_USIM/EF_MILENAGE_CFG:
  481. self.sim.select(GSM_SIM_MF)
  482. self.sim.card.SELECT_ADF_USIM()
  483. self.sim.select(SYSMO_ISIMSJA2_EF_MILENAGE_CFG)
  484. res = self._read_binary(self.sim.filelen)
  485. print(" * ADF_USIM/EF_MILENAGE_CFG:")
  486. print(SYSMO_ISIMSJA2_FILE_EF_MILENAGE_CFG(res.apdu))
  487. if self.sim.has_isim:
  488. # ADF_ISIM/EF_MILENAGE_CFG:
  489. self.sim.select(GSM_SIM_MF)
  490. self.sim.card.SELECT_ADF_ISIM()
  491. self.sim.select(SYSMO_ISIMSJA2_EF_MILENAGE_CFG)
  492. res = self._read_binary(self.sim.filelen)
  493. print(" * ADF_ISIM/EF_MILENAGE_CFG:")
  494. print(SYSMO_ISIMSJA2_FILE_EF_MILENAGE_CFG(res.apdu))
  495. # ADF_USIM/EF_USIM_SQN:
  496. self.sim.select(GSM_SIM_MF)
  497. self.sim.card.SELECT_ADF_USIM()
  498. self.sim.select(SYSMO_ISIMSJA2_EF_USIM_SQN)
  499. res = self._read_binary(self.sim.filelen)
  500. print(" * ADF_USIM/EF_USIM_SQN:")
  501. print(SYSMO_ISIMSJA2_FILE_EF_USIM_SQN(res.apdu))
  502. if self.sim.has_isim:
  503. # ADF_USIM/EF_ISIM_SQN:
  504. self.sim.select(GSM_SIM_MF)
  505. self.sim.card.SELECT_ADF_ISIM()
  506. self.sim.select(SYSMO_ISIMSJA2_EF_USIM_SQN)
  507. res = self._read_binary(self.sim.filelen)
  508. print(" * ADF_ISIM/EF_ISIM_SQN:")
  509. print(SYSMO_ISIMSJA2_FILE_EF_USIM_SQN(res.apdu))
  510. # Show current KI value
  511. def show_ki_params(self):
  512. print("Reading KI value...")
  513. self._init()
  514. # Note: The KI is expected to be the same in all eligible files
  515. print(" * Reading...")
  516. self.__select_xsim_auth_key(isim = False, _2G = True)
  517. res = self._read_binary(self.sim.filelen)
  518. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_2G(res.apdu)
  519. print(" * Current KI setting:")
  520. print(" KI: " + hexdump(ef.key))
  521. print("")
  522. # Program new KI value
  523. def write_ki_params(self, ki):
  524. print("Writing KI value...")
  525. self._init()
  526. print(" * New KI setting:")
  527. print(" KI: " + hexdump(ki))
  528. print(" * Programming...")
  529. self.__select_xsim_auth_key(isim = False, _2G = True)
  530. res = self._read_binary(self.sim.filelen)
  531. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_2G(res.apdu)
  532. ef.key = ki
  533. self.sim.update_binary(ef.encode())
  534. self.__select_xsim_auth_key(isim = False, _2G = False)
  535. res = self._read_binary(self.sim.filelen)
  536. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu)
  537. ef.key = ki
  538. self.sim.update_binary(ef.encode())
  539. if self.sim.has_isim:
  540. self.__select_xsim_auth_key(isim = True, _2G = False)
  541. res = self._read_binary(self.sim.filelen)
  542. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu)
  543. ef.key = ki
  544. self.sim.update_binary(ef.encode())
  545. print("")
  546. # Show current athentication parameters
  547. # (Which algorithim is used for which rat?)
  548. def show_auth_params(self):
  549. print("Reading Authentication parameters...")
  550. self._init()
  551. print(" * Reading...")
  552. self.__select_xsim_auth_key(isim = False, _2G = True)
  553. res = self._read_binary(self.sim.filelen)
  554. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_2G(res.apdu)
  555. algo_2g = ef.algo
  556. self.__select_xsim_auth_key(isim = False, _2G = False)
  557. res = self._read_binary(self.sim.filelen)
  558. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu)
  559. algo_3g = ef.algo
  560. print(" * Current algorithm setting:")
  561. print(" 2G: %d=%s" % (algo_2g, id_to_str(sysmo_isimsja2_algorithms, algo_2g)))
  562. print(" 3G: %d=%s" % (algo_3g, id_to_str(sysmo_isimsja2_algorithms, algo_3g)))
  563. print("")
  564. # Program new authentication parameters
  565. def write_auth_params(self, algo_2g_str, algo_3g_str):
  566. print("Programming Authentication parameters...")
  567. self._init()
  568. if algo_2g_str.isdigit():
  569. algo_2g = int(algo_2g_str)
  570. else:
  571. algo_2g = str_to_id(sysmo_isimsja2_algorithms, algo_2g_str)
  572. if algo_3g_str.isdigit():
  573. algo_3g = int(algo_3g_str)
  574. else:
  575. algo_3g = str_to_id(sysmo_isimsja2_algorithms, algo_3g_str)
  576. print(" * New algorithm setting:")
  577. print(" 2G: %d=%s" % (algo_2g, id_to_str(sysmo_isimsja2_algorithms, algo_2g)))
  578. print(" 3G: %d=%s" % (algo_3g, id_to_str(sysmo_isimsja2_algorithms, algo_3g)))
  579. print(" * Programming...")
  580. self.__select_xsim_auth_key(isim = False, _2G = True)
  581. res = self._read_binary(self.sim.filelen)
  582. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_2G(res.apdu)
  583. ef.algo = algo_2g
  584. self.sim.update_binary(ef.encode())
  585. self.__select_xsim_auth_key(isim = False, _2G = False)
  586. res = self._read_binary(self.sim.filelen)
  587. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu)
  588. ef.algo = algo_3g
  589. self.sim.update_binary(ef.encode())
  590. if self.sim.has_isim:
  591. self.__select_xsim_auth_key(isim = True, _2G = False)
  592. res = self._read_binary(self.sim.filelen)
  593. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu)
  594. ef.algo = algo_3g
  595. self.sim.update_binary(ef.encode())
  596. print("")
  597. # Show current OPc value
  598. def show_opc_params(self):
  599. print("Reading OP/c value...")
  600. self._init()
  601. # Note: The OPc is expected to be the same in all eligible files
  602. print(" * Reading...")
  603. self.__select_xsim_auth_key(isim = False, _2G = False)
  604. res = self._read_binary(self.sim.filelen)
  605. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu)
  606. if ef.use_opc:
  607. mode_str = "OPc"
  608. else:
  609. mode_str = "OP"
  610. print(" * Current OP/OPc setting:")
  611. print(" %s: %s" % (mode_str, hexdump(ef.opc)))
  612. print("")
  613. # Program new OPc value
  614. def write_opc_params(self, select, op):
  615. if select:
  616. print("Writing OPc value...")
  617. mode_str = "OPc"
  618. else:
  619. print("Writing OP value...")
  620. mode_str = "OP"
  621. self._init()
  622. print(" * New OPc setting:")
  623. print(" %s: %s" % (mode_str, hexdump(op)))
  624. print(" * Programming...")
  625. self.__select_xsim_auth_key(isim = False, _2G = True)
  626. res = self._read_binary(self.sim.filelen)
  627. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY_2G(res.apdu)
  628. ef.opc = op
  629. ef.use_opc = bool(select)
  630. self.sim.update_binary(ef.encode())
  631. if self.sim.has_isim:
  632. self.__select_xsim_auth_key(isim = True, _2G = False)
  633. res = self._read_binary(self.sim.filelen)
  634. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu)
  635. ef.opc = op
  636. ef.use_opc = bool(select)
  637. self.sim.update_binary(ef.encode())
  638. self.__select_xsim_auth_key(isim = False, _2G = False)
  639. res = self._read_binary(self.sim.filelen)
  640. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_AUTH_KEY(res.apdu)
  641. ef.opc = op
  642. ef.use_opc = bool(select)
  643. self.sim.update_binary(ef.encode())
  644. print("")
  645. # Show current milenage SQN parameters
  646. def show_milenage_sqn_params(self):
  647. print("Reading Milenage Sequence parameters...")
  648. self._init()
  649. print(" * Current SQN Configuration for ADF_USIM:")
  650. self.sim.select(GSM_SIM_MF)
  651. self.sim.card.SELECT_ADF_USIM()
  652. self.sim.select(SYSMO_ISIMSJA2_EF_USIM_SQN)
  653. res = self._read_binary(self.sim.filelen)
  654. print(SYSMO_ISIMSJA2_FILE_EF_USIM_SQN(res.apdu))
  655. if self.sim.has_isim:
  656. print(" * Current SQN Configuration for ADF_ISIM:")
  657. self.sim.select(GSM_SIM_MF)
  658. self.sim.card.SELECT_ADF_ISIM()
  659. self.sim.select(SYSMO_ISIMSJA2_EF_USIM_SQN)
  660. res = self._read_binary(self.sim.filelen)
  661. print(SYSMO_ISIMSJA2_FILE_EF_USIM_SQN(res.apdu))
  662. print("")
  663. # Reset milenage SQN configuration
  664. def reset_milenage_sqn_params(self):
  665. print(" * Resetting SQN Configuration to defaults...")
  666. self._init()
  667. print(" * Resetting...")
  668. self.sim.select(GSM_SIM_MF)
  669. self.sim.card.SELECT_ADF_USIM()
  670. self.sim.select(SYSMO_ISIMSJA2_EF_USIM_SQN)
  671. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_SQN()
  672. self.sim.update_binary(ef.encode())
  673. if self.sim.has_isim:
  674. self.sim.card.SELECT_ADF_ISIM()
  675. self.sim.select(SYSMO_ISIMSJA2_EF_USIM_SQN)
  676. ef = SYSMO_ISIMSJA2_FILE_EF_USIM_SQN()
  677. self.sim.update_binary(ef.encode())
  678. print("")