mirror of https://gerrit.osmocom.org/pysim
WIP: Add option to set UE operation mode in EF_AD (Administrative Data)
Use ``--opmode=OPMODE`` in cmdline mode or column ``OPMODE`` in csv mode to specify OPMODE as listed below. Details: The ``EF_AD`` field contains administrative data (AD). It consists of four bytes ``B1``, ``B2``, ``B3``, ``B4``, and optionally further bytes for future use. Previous implementation only sets the MNC field appropriately (located in `B4`) and sets all other bits/bytes to 0. However, `B1` also defines the *UE operation mode* (see below). For type approval operations, such as testing with a test uSIM, this value could be set to `0x80` rather than `0x00`(= normal operation). This may unlock some UE capabilities that are restricted in normal operation mode. Excerpt from [ETSI TS 131 102, 4.2.18](https://www.etsi.org/deliver/etsi_ts/131100_131199/131102/04.15.00_60/ts_131102v041500p.pdf): ``` B1 - UE operation mode: Coding: Initial value - '00' normal operation. - '80' type approval operations. - '01' normal operation + specific facilities. - '81' type approval operations + specific facilities. - '02' maintenance (off line). - '04' cell test operation. B2 - Additional information: Coding: Reserved for future use B3 - Additional information: Coding: - B3.b1: OFM setting (Ciphering Indicator) - B3.others: Reserved for future use B4 - Length of MNC in the IMSI: Coding: - B4.b4..B4.b1: length: '0010' (= 2) or '0011' (=3) - B4.others: Reserved for future use ``` **Legend:** Byte X, bit Y: BX.bY Further reading: https://nickvsnetworking.com/usim-basics/ Change-Id: Ie9040c6b127c268878a0845ed73d0918ec6bbb08
This commit is contained in:
parent
08028d02dc
commit
d0505bdb55
|
@ -37,7 +37,7 @@ from pySim.commands import SimCardCommands
|
|||
from pySim.transport import init_reader
|
||||
from pySim.cards import _cards_classes, card_detect
|
||||
from pySim.utils import h2b, swap_nibbles, rpad, derive_milenage_opc, calculate_luhn, dec_iccid
|
||||
from pySim.ts_51_011 import EF
|
||||
from pySim.ts_51_011 import EF, EF_AD
|
||||
from pySim.card_handler import *
|
||||
from pySim.utils import *
|
||||
|
||||
|
@ -143,6 +143,11 @@ def parse_options():
|
|||
parser.add_option("--acc", dest="acc",
|
||||
help="Set ACC bits (Access Control Code). not all card types are supported",
|
||||
)
|
||||
parser.add_option("--opmode", dest="opmode", type="choice",
|
||||
help="Set UE Operation Mode in EF.AD (Administrative Data)",
|
||||
default=None,
|
||||
choices=['{:02X}'.format(m) for m in list(EF_AD.OP_MODE.keys())],
|
||||
)
|
||||
parser.add_option("--epdgid", dest="epdgid",
|
||||
help="Set Home Evolved Packet Data Gateway (ePDG) Identifier. (Only FQDN format supported)",
|
||||
)
|
||||
|
@ -472,6 +477,7 @@ def gen_parameters(opts):
|
|||
'ims_hdomain': opts.ims_hdomain,
|
||||
'impi' : opts.impi,
|
||||
'impu' : opts.impu,
|
||||
'opmode': opts.opmode,
|
||||
}
|
||||
|
||||
|
||||
|
@ -490,6 +496,8 @@ def print_parameters(params):
|
|||
if 'acc' in params:
|
||||
s.append(" > ACC : %(acc)s")
|
||||
s.append(" > ADM1(hex): %(pin_adm)s")
|
||||
if 'opmode' in params:
|
||||
s.append(" > OPMODE : %(opmode)s")
|
||||
print("\n".join(s) % params)
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
from pySim.ts_51_011 import EF, DF
|
||||
from pySim.ts_51_011 import EF, DF, EF_AD
|
||||
from pySim.ts_31_102 import EF_USIM_ADF_map
|
||||
from pySim.ts_31_103 import EF_ISIM_ADF_map
|
||||
from pySim.utils import *
|
||||
|
@ -153,22 +153,52 @@ class Card(object):
|
|||
data, sw = self._scc.update_record(EF['SMSP'], 1, rpad(smsp, 84))
|
||||
return sw
|
||||
|
||||
def update_ad(self, mnc):
|
||||
#See also: 3GPP TS 31.102, chapter 4.2.18
|
||||
mnclen = len(str(mnc))
|
||||
if mnclen == 1:
|
||||
mnclen = 2
|
||||
if mnclen > 3:
|
||||
raise RuntimeError('unable to calculate proper mnclen')
|
||||
def update_ad(self, mnc=None, opmode=None, ofm=None):
|
||||
"""
|
||||
Update Administrative Data (AD)
|
||||
|
||||
data, sw = self._scc.read_binary(EF['AD'], length=None, offset=0)
|
||||
See Sec. "4.2.18 EF_AD (Administrative Data)"
|
||||
in 3GPP TS 31.102 for the details of the EF_AD contents.
|
||||
|
||||
# Reset contents to EF.AD in case the file is uninintalized
|
||||
if data.lower() == "ffffffff":
|
||||
data = "00000000"
|
||||
Set any parameter to None to keep old value(s) on card.
|
||||
|
||||
content = data[0:6] + "%02X" % mnclen
|
||||
data, sw = self._scc.update_binary(EF['AD'], content)
|
||||
Parameters:
|
||||
mnc (str): MNC of IMSI
|
||||
opmode (Hex-str, 1 Byte): MS Operation Mode
|
||||
ofm (Hex-str, 1 Byte): Operational Feature Monitor (OFM) aka Ciphering Indicator
|
||||
|
||||
Returns:
|
||||
str: Return code of write operation
|
||||
"""
|
||||
|
||||
ad = EF_AD()
|
||||
|
||||
# read from card
|
||||
raw_hex_data, sw = self._scc.read_binary(EF['AD'], length=None, offset=0)
|
||||
raw_bin_data = h2b(raw_hex_data)
|
||||
abstract_data = ad.decode_bin(raw_bin_data)
|
||||
|
||||
# perform updates
|
||||
if mnc:
|
||||
mnclen = len(str(mnc))
|
||||
if mnclen == 1:
|
||||
mnclen = 2
|
||||
if mnclen > 3:
|
||||
raise RuntimeError('invalid length of mnc "{}"'.format(mnc))
|
||||
abstract_data['len_of_mnc_in_imsi'] = mnclen
|
||||
if opmode:
|
||||
opmode_symb = ad.OP_MODE.get(int(opmode, 16))
|
||||
if opmode_symb:
|
||||
abstract_data['ms_operation_mode'] = opmode_symb
|
||||
else:
|
||||
raise RuntimeError('invalid opmode "{}"'.format(opmode))
|
||||
if ofm:
|
||||
abstract_data['specific_facilities']['ofm'] = bool(int(ofm, 16))
|
||||
|
||||
# write to card
|
||||
raw_bin_data = ad.encode_bin(abstract_data)
|
||||
raw_hex_data = b2h(raw_bin_data)
|
||||
data, sw = self._scc.update_binary(EF['AD'], raw_hex_data)
|
||||
return sw
|
||||
|
||||
def read_spn(self):
|
||||
|
@ -915,8 +945,12 @@ class SysmoUSIMSJS1(UsimCard):
|
|||
print("Programming HPLMNwAcT failed with code %s"%sw)
|
||||
|
||||
# EF.AD
|
||||
if p.get('mcc') and p.get('mnc'):
|
||||
sw = self.update_ad(p['mnc'])
|
||||
if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
|
||||
if p.get('mcc') and p.get('mnc'):
|
||||
mnc = p['mnc']
|
||||
else:
|
||||
mnc = None
|
||||
sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
|
||||
if sw != '9000':
|
||||
print("Programming AD failed with code %s"%sw)
|
||||
|
||||
|
@ -1205,8 +1239,12 @@ class WavemobileSim(UsimCard):
|
|||
print("Programming OPLMNwAcT failed with code %s"%sw)
|
||||
|
||||
# EF.AD
|
||||
if p.get('mcc') and p.get('mnc'):
|
||||
sw = self.update_ad(p['mnc'])
|
||||
if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
|
||||
if p.get('mcc') and p.get('mnc'):
|
||||
mnc = p['mnc']
|
||||
else:
|
||||
mnc = None
|
||||
sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
|
||||
if sw != '9000':
|
||||
print("Programming AD failed with code %s"%sw)
|
||||
|
||||
|
@ -1300,8 +1338,12 @@ class SysmoISIMSJA2(UsimCard, IsimCard):
|
|||
print("Programming HPLMNwAcT failed with code %s"%sw)
|
||||
|
||||
# EF.AD
|
||||
if p.get('mcc') and p.get('mnc'):
|
||||
sw = self.update_ad(p['mnc'])
|
||||
if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
|
||||
if p.get('mcc') and p.get('mnc'):
|
||||
mnc = p['mnc']
|
||||
else:
|
||||
mnc = None
|
||||
sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
|
||||
if sw != '9000':
|
||||
print("Programming AD failed with code %s"%sw)
|
||||
|
||||
|
|
Loading…
Reference in New Issue