2017-02-23 13:47:38 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
"""
|
|
|
|
Gadgets to modify SYSMO USIM SJS1 parameters
|
|
|
|
|
|
|
|
(C) 2017 by Sysmocom s.f.m.c. GmbH
|
|
|
|
All Rights Reserved
|
|
|
|
|
|
|
|
Author: Philipp Maier
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Some gadgets to handle functions specific to Sysmo USIM SJS1. The gadgets are
|
|
|
|
# organized as a loose collection of python functions. Each function serves
|
|
|
|
# a specific task (e.g. modifiying the auth parameters). For each task two
|
|
|
|
# functions are implemented sysmo_usim_show_...() to inspect the data that is
|
|
|
|
# intended to be modified and sysmo_usim_write_...() to perform the actual
|
|
|
|
# modification task.
|
|
|
|
|
|
|
|
# Partial File tree:
|
|
|
|
# The following tree is incomplete, it just contains the propritary files we
|
|
|
|
# need to perform the tasks implemented below:
|
|
|
|
#
|
|
|
|
# [MF 0x3F00]
|
|
|
|
# |
|
|
|
|
# +--[DF_AUTH 0x7FCC]
|
|
|
|
# | |
|
|
|
|
# | +--[EF_AUTH 0x6F00]
|
|
|
|
# | |
|
|
|
|
# | +--[EF_MLNGC 0x6F01]
|
|
|
|
# |
|
|
|
|
# +--[DF_GSM 0x7F20]
|
|
|
|
# |
|
|
|
|
# +--[EF_OPC 0x00F7]
|
|
|
|
# |
|
|
|
|
# +--[EF_KI 0x00FF]
|
2018-08-08 08:49:26 +00:00
|
|
|
# |
|
|
|
|
# +--[EF_IMSI 0x6F07]
|
2017-02-23 13:47:38 +00:00
|
|
|
|
2017-08-16 13:18:09 +00:00
|
|
|
import sys
|
2017-02-23 13:47:38 +00:00
|
|
|
from card import *
|
|
|
|
from simcard import *
|
2017-08-16 13:18:09 +00:00
|
|
|
from utils import *
|
2017-02-23 13:47:38 +00:00
|
|
|
|
|
|
|
# Files (propritary)
|
|
|
|
SYSMO_USIMSJS1_EF_KI = [0x00, 0xFF]
|
|
|
|
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_EF_AUTH = [0x6F, 0x00]
|
|
|
|
SYSMO_USIMSJS1_EF_MLNGC = [0x6F, 0x01]
|
2017-08-16 15:22:00 +00:00
|
|
|
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
|
2017-02-23 13:47:38 +00:00
|
|
|
|
|
|
|
# CHV Types
|
|
|
|
SYSMO_USIMSJS1_ADM1 = 0x0A
|
|
|
|
|
|
|
|
# Authentication algorithms (See sysmousim.pdf cap. 8.5)
|
|
|
|
SYSMO_USIMSJS1_ALGO_MILENAGE = 0x01
|
|
|
|
SYSMO_USIMSJS1_ALGO_COMP12V1 = 0x03
|
|
|
|
SYSMO_USIMSJS1_ALGO_XOR2G = 0x04
|
|
|
|
SYSMO_USIMSJS1_ALGO_COMP128V2 = 0x06
|
|
|
|
SYSMO_USIMSJS1_ALGO_COMP128V3 = 0x07
|
|
|
|
SYSMO_USIMSJS1_ALGO_XOR3G = 0x08
|
|
|
|
|
|
|
|
# Application identifier
|
|
|
|
SYSMO_USIM_AID = [0xa0, 0x00, 0x00, 0x00, 0x87, 0x10, 0x02]
|
|
|
|
|
|
|
|
# Default content of record No.1 in EF.DIR
|
|
|
|
SYSMO_USIM_EF_DIR_REC_1_CONTENT = [0x61, 0x19, 0x4f, 0x10] + SYSMO_USIM_AID + \
|
|
|
|
[0xff, 0xff, 0xff, 0xff, 0x89, 0x07, 0x09, 0x00, 0x00, 0x50, 0x05,
|
|
|
|
0x55, 0x53, 0x69, 0x6d, 0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff]
|
|
|
|
|
|
|
|
# Abstraction for the file structure of EF.MLNGC, which holds the
|
|
|
|
# parameters of the milenage authentication algorithm
|
|
|
|
class SYSMO_USIMSJS1_FILE_EF_MLNGC:
|
|
|
|
# Default parameters, see also sysmousim-manual.pdf,
|
|
|
|
# cap. 8.6 "Milenage Configuration (Ci/Ri)
|
|
|
|
C1 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
|
|
|
C2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]
|
|
|
|
C3 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02]
|
|
|
|
C4 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04]
|
|
|
|
C5 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08]
|
|
|
|
R1 = 0x40
|
|
|
|
R2 = 0x00
|
|
|
|
R3 = 0x20
|
|
|
|
R4 = 0x40
|
|
|
|
R5 = 0x60
|
|
|
|
|
|
|
|
def __init__(self, content = None):
|
|
|
|
if content == None:
|
|
|
|
return
|
|
|
|
if len(content) != 85:
|
|
|
|
return
|
|
|
|
self.C1 = content[0:16]
|
|
|
|
self.C2 = content[16:32]
|
|
|
|
self.C3 = content[32:48]
|
|
|
|
self.C4 = content[48:64]
|
|
|
|
self.C5 = content[64:80]
|
|
|
|
self.R1 = content[80]
|
|
|
|
self.R2 = content[81]
|
|
|
|
self.R3 = content[82]
|
|
|
|
self.R4 = content[83]
|
|
|
|
self.R5 = content[84]
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
dump = " C1: " + hexdump(self.C1) + "\n"
|
|
|
|
dump += " C2: " + hexdump(self.C2) + "\n"
|
|
|
|
dump += " C3: " + hexdump(self.C3) + "\n"
|
|
|
|
dump += " C4: " + hexdump(self.C4) + "\n"
|
|
|
|
dump += " C5: " + hexdump(self.C5) + "\n"
|
|
|
|
dump += " R1: " + str(hex(self.R1)) + "\n"
|
|
|
|
dump += " R2: " + str(hex(self.R2)) + "\n"
|
|
|
|
dump += " R3: " + str(hex(self.R3)) + "\n"
|
|
|
|
dump += " R4: " + str(hex(self.R4)) + "\n"
|
|
|
|
dump += " R5: " + str(hex(self.R5))
|
|
|
|
return dump
|
|
|
|
|
2017-08-16 15:22:00 +00:00
|
|
|
class SYSMO_USIMSJS1_FILE_EF_SQNC:
|
|
|
|
# Default parameters
|
|
|
|
ind_size_bits = 5
|
|
|
|
sqn_check_enabled = True
|
2017-08-17 12:36:19 +00:00
|
|
|
sqn_age_limit_enabled = False
|
2017-08-16 15:22:00 +00:00
|
|
|
sqn_max_delta_enabled = True
|
|
|
|
sqnms_offset = 0
|
2017-08-17 12:36:19 +00:00
|
|
|
max_delta = 2**28 << ind_size_bits
|
2017-08-16 15:22:00 +00:00
|
|
|
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))
|
2017-08-17 11:15:39 +00:00
|
|
|
self.ind_size_bits = content[0] & 0xf
|
|
|
|
self.sqn_check_enabled = bool(content[0] & 0x10)
|
|
|
|
self.sqn_age_limit_enabled = bool(content[0] & 0x20)
|
|
|
|
self.sqn_max_delta_enabled = bool(content[0] & 0x40)
|
2017-08-17 11:22:19 +00:00
|
|
|
self.sqnms_offset = list_to_int(content[1:3])/6
|
2017-08-16 15:22:00 +00:00
|
|
|
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)
|
2017-08-17 11:22:19 +00:00
|
|
|
dump += "%sSQNms Offset (into SQN array): %u\n" % (pfx, self.sqnms_offset)
|
2017-08-16 15:22:00 +00:00
|
|
|
dump += "%sMax Delta: %u\n" % (pfx, self.max_delta)
|
|
|
|
dump += "%sAge Limit: %u\n" % (pfx, self.age_limit)
|
|
|
|
return dump
|
|
|
|
|
2017-08-17 12:36:19 +00:00
|
|
|
def encode(self):
|
|
|
|
out = list(range(0, 3))
|
|
|
|
out[0] = self.ind_size_bits & 0x0f
|
|
|
|
if self.sqn_check_enabled:
|
|
|
|
out[0] |= 0x10
|
|
|
|
if self.sqn_age_limit_enabled:
|
|
|
|
out[0] |= 0x20
|
|
|
|
if self.sqn_max_delta_enabled:
|
|
|
|
out[0] |= 0x40
|
|
|
|
out[1] = (self.sqnms_offset*6) & 0xff
|
|
|
|
out[2] = (self.sqnms_offset*6) >> 8
|
|
|
|
out += int_to_list(self.max_delta, 6)
|
|
|
|
out += int_to_list(self.age_limit, 6)
|
|
|
|
return out
|
|
|
|
|
2017-08-16 15:22:00 +00:00
|
|
|
class SYSMO_USIMSJS1_FILE_EF_SQNA:
|
|
|
|
seq_array = []
|
|
|
|
|
|
|
|
def __init__(self, content, ind = 5):
|
|
|
|
if content == None:
|
2017-08-17 12:36:19 +00:00
|
|
|
for i in range(0, 2**ind):
|
|
|
|
self.seq_array.append(0)
|
2017-08-16 15:22:00 +00:00
|
|
|
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
|
|
|
|
|
2017-08-17 12:36:19 +00:00
|
|
|
def encode(self):
|
|
|
|
out = []
|
|
|
|
for i in self.seq_array:
|
|
|
|
out += int_to_list(i, 6)
|
|
|
|
return out
|
|
|
|
|
2017-02-23 13:47:38 +00:00
|
|
|
|
|
|
|
# Initalize card (select master file)
|
|
|
|
def sysmo_usim_init(sim):
|
|
|
|
print " * Initalizing..."
|
|
|
|
sim.select(GSM_SIM_MF)
|
|
|
|
|
|
|
|
|
|
|
|
# Authenticate as administrator
|
2017-03-17 15:43:35 +00:00
|
|
|
def sysmo_usim_admin_auth(sim, adm1, force = False):
|
|
|
|
rc = True
|
|
|
|
rem_attemts = sim.chv_retrys(SYSMO_USIMSJS1_ADM1)
|
|
|
|
|
|
|
|
print " * Remaining attempts: " + str(rem_attemts)
|
|
|
|
|
|
|
|
# Stop if a decreased ADM1 retry counter is detected
|
|
|
|
if(rem_attemts < 3) and force == False:
|
|
|
|
print " * Error: Only two authentication attemts remaining, we don't"
|
|
|
|
print " want to risk another failed authentication attempt!"
|
|
|
|
print " (double check ADM1 and use option -f to override)"
|
|
|
|
return False
|
|
|
|
|
|
|
|
# Try to authenticate
|
|
|
|
try:
|
|
|
|
print " * Authenticating..."
|
|
|
|
sim.verify_chv(adm1, SYSMO_USIMSJS1_ADM1)
|
|
|
|
print " * Authentication successful"
|
|
|
|
except:
|
|
|
|
print " * Error: Authentication failed!"
|
|
|
|
rc = False
|
|
|
|
|
|
|
|
# Read back and display remaining attemts
|
|
|
|
rem_attemts = sim.chv_retrys(SYSMO_USIMSJS1_ADM1)
|
|
|
|
print " * Remaining attempts: " + str(rem_attemts)
|
|
|
|
|
|
|
|
return rc
|
2017-02-23 13:47:38 +00:00
|
|
|
|
2017-12-14 04:22:49 +00:00
|
|
|
sysmo_usim_algorithms = (
|
|
|
|
(1, 'MILENAGE'),
|
|
|
|
(3, 'COMP128v1'),
|
|
|
|
(4, 'XOR-2G'),
|
|
|
|
(5, 'GBA'),
|
|
|
|
(6, 'COMP128v2'),
|
|
|
|
(7, 'COMP128v3'),
|
|
|
|
(8, 'XOR-3G'),
|
|
|
|
(9, 'CIS-B'),
|
|
|
|
)
|
|
|
|
|
|
|
|
sysmo_usim_algorithms_dict_by_nr = dict(sysmo_usim_algorithms)
|
|
|
|
sysmo_usim_algorithms_dict_by_name = dict([(name.upper(), nr) for nr, name in sysmo_usim_algorithms])
|
|
|
|
|
|
|
|
def sysmo_usim_algo_to_str(alg_nr):
|
|
|
|
return sysmo_usim_algorithms_dict_by_nr.get(alg_nr) or 'INVALID'
|
|
|
|
|
|
|
|
def sysmo_usim_str_to_algo(alg_str):
|
|
|
|
alg_nr = sysmo_usim_algorithms_dict_by_name.get(alg_str.upper())
|
|
|
|
if alg_nr is None:
|
|
|
|
raise ValueError('Unknown Algorithm %s' % alg_str)
|
|
|
|
return alg_nr
|
2017-02-23 13:47:38 +00:00
|
|
|
|
|
|
|
# Show current athentication parameters
|
|
|
|
# (Which algorithim is used for which rat?)
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_show_auth_params(sim):
|
2017-02-23 13:47:38 +00:00
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * Reading..."
|
|
|
|
sim.select(SYSMO_USIMSJS1_DF_AUTH)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_AUTH)
|
|
|
|
res = sim.read_binary(0x02)
|
|
|
|
|
2017-12-14 04:22:49 +00:00
|
|
|
algo_2g, algo_3g = res.apdu[:2]
|
|
|
|
|
2017-02-23 13:47:38 +00:00
|
|
|
print " * Current algorithm setting:"
|
2017-12-14 04:22:49 +00:00
|
|
|
print " 2G: %d=%s" % (algo_2g, sysmo_usim_algo_to_str(algo_2g))
|
|
|
|
print " 3G: %d=%s" % (algo_3g, sysmo_usim_algo_to_str(algo_3g))
|
2017-02-23 13:47:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Program new authentication parameters
|
2017-08-16 20:38:38 +00:00
|
|
|
def sysmo_usim_write_auth_params(sim, algo_2g_str, algo_3g_str):
|
2018-08-07 13:41:45 +00:00
|
|
|
|
|
|
|
if algo_2g_str.isdigit():
|
|
|
|
algo_2g = int(algo_2g_str)
|
|
|
|
else:
|
|
|
|
algo_2g = sysmo_usim_str_to_algo(algo_2g_str)
|
|
|
|
|
|
|
|
if algo_3g_str.isdigit():
|
|
|
|
algo_3g = int(algo_2g_str)
|
|
|
|
else:
|
|
|
|
algo_3g = sysmo_usim_str_to_algo(algo_3g_str)
|
2017-08-16 20:38:38 +00:00
|
|
|
|
2017-02-23 13:47:38 +00:00
|
|
|
print " * New algorithm setting:"
|
2017-12-14 04:22:49 +00:00
|
|
|
print " 2G: %d=%s" % (algo_2g, sysmo_usim_algo_to_str(algo_2g))
|
|
|
|
print " 3G: %d=%s" % (algo_3g, sysmo_usim_algo_to_str(algo_3g))
|
2017-02-23 13:47:38 +00:00
|
|
|
|
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * Programming..."
|
|
|
|
sim.select(SYSMO_USIMSJS1_DF_AUTH)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_AUTH)
|
|
|
|
sim.update_binary([algo_2g,algo_3g])
|
|
|
|
|
2017-08-16 15:22:00 +00:00
|
|
|
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
|
|
|
|
|
2017-08-17 12:36:19 +00:00
|
|
|
def sysmo_usim_set_auth_counter(sim, ctr):
|
|
|
|
if ctr == "LOCKED":
|
|
|
|
ctr = 0
|
|
|
|
elif ctr == "DISABLED":
|
|
|
|
ctr = 0xFFFFFFFF
|
|
|
|
data = int_to_list(ctr, 4)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_AC)
|
|
|
|
res = sim.update_binary(data, offset=0)
|
|
|
|
if ctr == 0:
|
|
|
|
return "LOCKED"
|
|
|
|
elif ctr == 0xFFFFFFFF:
|
|
|
|
return "DISABLED"
|
|
|
|
else:
|
|
|
|
return ctr
|
|
|
|
|
2017-08-16 15:22:00 +00:00
|
|
|
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)
|
2018-08-08 09:22:09 +00:00
|
|
|
print " * Current SQN Configuration:"
|
2017-08-16 15:22:00 +00:00
|
|
|
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)
|
2018-08-08 09:22:09 +00:00
|
|
|
print " * Current SQN Array:"
|
2017-08-16 15:22:00 +00:00
|
|
|
print str(ef_sqna)
|
|
|
|
|
|
|
|
auth_ctr = sysmo_usim_get_auth_counter(sim)
|
|
|
|
print "* Authentication Counter: %s\n" % auth_ctr
|
2017-02-23 13:47:38 +00:00
|
|
|
|
2017-08-17 12:36:19 +00:00
|
|
|
def sysmo_usim_reset_milenage_sqn_params(sim):
|
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
2018-07-04 12:40:46 +00:00
|
|
|
print " * Resetting SQN Configuration to defaults..."
|
2017-08-17 12:36:19 +00:00
|
|
|
|
|
|
|
sim.card.SELECT_ADF_USIM()
|
|
|
|
ef_sqnc = SYSMO_USIMSJS1_FILE_EF_SQNC(None)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_SQNC)
|
|
|
|
res = sim.update_binary(ef_sqnc.encode())
|
|
|
|
|
|
|
|
ef_sqna = SYSMO_USIMSJS1_FILE_EF_SQNA(None, ef_sqnc.ind_size_bits)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_SQNA)
|
|
|
|
res = sim.update_binary(ef_sqna.encode())
|
|
|
|
|
|
|
|
sysmo_usim_set_auth_counter(sim, "DISABLED")
|
|
|
|
|
2017-02-23 13:47:38 +00:00
|
|
|
# Show current milenage parameters
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_show_milenage_params(sim):
|
2017-02-23 13:47:38 +00:00
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
sim.select(SYSMO_USIMSJS1_DF_AUTH)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_MLNGC)
|
|
|
|
|
|
|
|
print " * Reading..."
|
|
|
|
ef_mlngc = SYSMO_USIMSJS1_FILE_EF_MLNGC()
|
|
|
|
res = sim.read_binary(16, offset = 0)
|
|
|
|
ef_mlngc.C1 = res.apdu
|
|
|
|
res = sim.read_binary(16, offset = 16)
|
|
|
|
ef_mlngc.C2 = res.apdu
|
|
|
|
res = sim.read_binary(16, offset = 32)
|
|
|
|
ef_mlngc.C3 = res.apdu
|
|
|
|
res = sim.read_binary(16, offset = 48)
|
|
|
|
ef_mlngc.C4 = res.apdu
|
|
|
|
res = sim.read_binary(16, offset = 64)
|
|
|
|
ef_mlngc.C5 = res.apdu
|
|
|
|
res = sim.read_binary(1, offset = 80)
|
|
|
|
ef_mlngc.R1 = res.apdu[0]
|
|
|
|
res = sim.read_binary(1, offset = 81)
|
|
|
|
ef_mlngc.R2 = res.apdu[0]
|
|
|
|
res = sim.read_binary(1, offset = 82)
|
|
|
|
ef_mlngc.R3 = res.apdu[0]
|
|
|
|
res = sim.read_binary(1, offset = 83)
|
|
|
|
ef_mlngc.R4 = res.apdu[0]
|
|
|
|
res = sim.read_binary(1, offset = 84)
|
|
|
|
ef_mlngc.R5 = res.apdu[0]
|
|
|
|
|
|
|
|
print " * Current Milenage Parameters in (EF.MLNGC):"
|
|
|
|
print str(ef_mlngc)
|
|
|
|
|
|
|
|
|
|
|
|
# Write new milenage parameters
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_write_milenage_params(sim, ef_mlngc):
|
2017-02-23 13:47:38 +00:00
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * New Milenage Parameters for (EF.MLNGC):"
|
|
|
|
print str(ef_mlngc)
|
|
|
|
|
|
|
|
sim.select(SYSMO_USIMSJS1_DF_AUTH)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_MLNGC)
|
|
|
|
|
|
|
|
print " * Programming..."
|
|
|
|
sim.update_binary(ef_mlngc.C1, offset = 0)
|
|
|
|
sim.update_binary(ef_mlngc.C2, offset = 16)
|
|
|
|
sim.update_binary(ef_mlngc.C3, offset = 32)
|
|
|
|
sim.update_binary(ef_mlngc.C4, offset = 48)
|
|
|
|
sim.update_binary(ef_mlngc.C5, offset = 64)
|
|
|
|
sim.update_binary([ef_mlngc.R1], offset = 80)
|
|
|
|
sim.update_binary([ef_mlngc.R2], offset = 81)
|
|
|
|
sim.update_binary([ef_mlngc.R3], offset = 82)
|
|
|
|
sim.update_binary([ef_mlngc.R4], offset = 83)
|
|
|
|
sim.update_binary([ef_mlngc.R5], offset = 84)
|
|
|
|
|
|
|
|
|
2017-08-16 21:15:34 +00:00
|
|
|
def sysmo_usim_opcmode2str(mode):
|
|
|
|
if mode == 1:
|
|
|
|
return 'OPc'
|
|
|
|
elif mode == 0:
|
|
|
|
return 'OP'
|
|
|
|
else:
|
|
|
|
raise ValueError('Unknown Mode ', mode)
|
|
|
|
|
|
|
|
|
2017-02-23 13:47:38 +00:00
|
|
|
# Show current OPc value
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_show_opc_params(sim):
|
2017-02-23 13:47:38 +00:00
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * Reading..."
|
2017-08-16 14:23:31 +00:00
|
|
|
sim.card.SELECT_ADF_USIM()
|
2017-02-23 13:47:38 +00:00
|
|
|
sim.select(SYSMO_USIMSJS1_EF_OPC)
|
|
|
|
res = sim.read_binary(17)
|
|
|
|
|
2017-08-16 21:15:34 +00:00
|
|
|
mode_str = sysmo_usim_opcmode2str(res.apdu[0])
|
|
|
|
|
|
|
|
print " * Current OP/OPc setting:"
|
|
|
|
print " %s: %s" % (mode_str, hexdump(res.apdu[1:]))
|
2017-02-23 13:47:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Program new OPc value
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_write_opc_params(sim, select, op):
|
2017-02-23 13:47:38 +00:00
|
|
|
print " * New OPc setting:"
|
2017-08-16 21:15:34 +00:00
|
|
|
print " %s: %s" % (sysmo_usim_opcmode2str(select), hexdump(op))
|
2017-02-23 13:47:38 +00:00
|
|
|
print " OP/OPc: " + hexdump(op)
|
|
|
|
|
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
sim.select(GSM_SIM_DF_GSM)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_OPC)
|
|
|
|
|
|
|
|
print " * Programming..."
|
|
|
|
sim.update_binary([select] + op)
|
|
|
|
|
|
|
|
|
2017-03-05 00:00:13 +00:00
|
|
|
# Show current KI value
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_show_ki_params(sim):
|
2017-03-05 00:00:13 +00:00
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * Reading..."
|
|
|
|
sim.select(GSM_SIM_DF_GSM)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_KI)
|
|
|
|
res = sim.read_binary(16)
|
|
|
|
|
|
|
|
print " * Current KI setting:"
|
|
|
|
print " KI: " + hexdump(res.apdu)
|
|
|
|
|
|
|
|
|
|
|
|
# Program new KI value
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_write_ki_params(sim, ki):
|
2017-03-05 00:00:13 +00:00
|
|
|
print " * New KI setting:"
|
|
|
|
print " KI: " + hexdump(ki)
|
|
|
|
|
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
sim.select(GSM_SIM_DF_GSM)
|
|
|
|
sim.select(SYSMO_USIMSJS1_EF_KI)
|
|
|
|
|
|
|
|
print " * Programming..."
|
|
|
|
sim.update_binary(ki)
|
|
|
|
|
|
|
|
|
2017-02-23 13:47:38 +00:00
|
|
|
# Show the enable status of the USIM application (app is enabled or disabled?)
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_show_usim_status(sim):
|
2017-02-23 13:47:38 +00:00
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * Reading..."
|
|
|
|
sim.select(GSM_USIM_EF_DIR)
|
|
|
|
res = sim.read_record(0x26, rec_no = 1)
|
|
|
|
|
|
|
|
print " * Current status of Record No.1 in EF.DIR:"
|
|
|
|
print " " + hexdump(res.apdu)
|
|
|
|
|
|
|
|
|
|
|
|
# Show the enable status of the USIM application (app is enabled or disabled?)
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_show_sim_mode(sim):
|
2017-02-23 13:47:38 +00:00
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * Reading..."
|
|
|
|
sim.select(GSM_USIM_EF_DIR)
|
|
|
|
res = sim.read_record(0x26, rec_no = 1)
|
|
|
|
|
|
|
|
print " * Current status of Record No. 1 in EF.DIR:"
|
|
|
|
print " " + hexdump(res.apdu)
|
|
|
|
|
|
|
|
if hexdump(SYSMO_USIM_AID) in hexdump(res.apdu):
|
|
|
|
print " ==> USIM application enabled"
|
|
|
|
else:
|
|
|
|
print " ==> USIM application disabled"
|
|
|
|
|
|
|
|
|
|
|
|
# Show the enable status of the USIM application (app is enabled or disabled?)
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_write_sim_mode(sim, usim_enabled = True):
|
2017-02-23 13:47:38 +00:00
|
|
|
if usim_enabled:
|
|
|
|
new_record = SYSMO_USIM_EF_DIR_REC_1_CONTENT
|
|
|
|
else:
|
|
|
|
new_record = [0xFF] * len(SYSMO_USIM_EF_DIR_REC_1_CONTENT)
|
|
|
|
|
|
|
|
print " * New status of Record No.1 in EF.DIR:"
|
|
|
|
print " " + hexdump(new_record)
|
|
|
|
if hexdump(SYSMO_USIM_AID) in hexdump(new_record):
|
|
|
|
print " ==> USIM application enabled"
|
|
|
|
else:
|
|
|
|
print " ==> USIM application disabled"
|
|
|
|
|
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * Programming..."
|
|
|
|
sim.select(GSM_USIM_EF_DIR)
|
|
|
|
sim.update_record(new_record, rec_no = 1)
|
|
|
|
|
|
|
|
|
2017-03-20 23:30:34 +00:00
|
|
|
# Show current ICCID value
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_show_iccid(sim):
|
2017-03-20 23:30:34 +00:00
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
print " * Reading..."
|
|
|
|
sim.select(GSM_SIM_EF_ICCID)
|
|
|
|
res = sim.read_binary(10)
|
|
|
|
|
|
|
|
print " * Current ICCID setting:"
|
|
|
|
print " ICCID: " + hexdump(swap_nibbles(res.apdu))
|
|
|
|
|
|
|
|
|
|
|
|
# Program new ICCID value
|
2017-08-16 08:04:39 +00:00
|
|
|
def sysmo_usim_write_iccid(sim, iccid):
|
2017-03-20 23:30:34 +00:00
|
|
|
print " * New ICCID setting:"
|
|
|
|
print " ICCID: " + hexdump(iccid)
|
|
|
|
|
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
sim.select(GSM_SIM_EF_ICCID)
|
|
|
|
|
|
|
|
print " * Programming..."
|
|
|
|
sim.update_binary(swap_nibbles(iccid))
|
2018-08-08 08:49:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Program new IMSI value
|
|
|
|
def sysmo_usim_write_imsi(sim, imsi):
|
|
|
|
print " * New ISMI setting:"
|
|
|
|
print " IMSI: " + hexdump(imsi)
|
|
|
|
|
|
|
|
sysmo_usim_init(sim)
|
|
|
|
|
|
|
|
sim.select(GSM_SIM_DF_GSM)
|
|
|
|
sim.select(GSM_SIM_EF_IMSI)
|
|
|
|
|
|
|
|
imsi = [len(imsi)] + swap_nibbles(imsi)
|
|
|
|
|
|
|
|
print " * Programming..."
|
|
|
|
sim.update_binary(imsi)
|