Change in pysim[master]: WIP: Add option to set UE operation mode in EF_AD (Administrative Data)

laforge gerrit-no-reply at lists.osmocom.org
Sun Apr 11 09:35:36 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/23632 )

Change subject: WIP: Add option to set UE operation mode in EF_AD (Administrative Data)
......................................................................

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
---
M pySim-prog.py
M pySim/cards.py
2 files changed, 71 insertions(+), 21 deletions(-)

Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/pySim-prog.py b/pySim-prog.py
index 7b1283b..0abd190 100755
--- a/pySim-prog.py
+++ b/pySim-prog.py
@@ -37,7 +37,7 @@
 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 @@
 	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 @@
 		'ims_hdomain': opts.ims_hdomain,
 		'impi' : opts.impi,
 		'impu' : opts.impu,
+		'opmode': opts.opmode,
 	}
 
 
@@ -490,6 +496,8 @@
 	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)
 
 
diff --git a/pySim/cards.py b/pySim/cards.py
index 8ac80bf..8489c97 100644
--- a/pySim/cards.py
+++ b/pySim/cards.py
@@ -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 @@
 		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 @@
 				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 @@
 				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 @@
 				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)
 

-- 
To view, visit https://gerrit.osmocom.org/c/pysim/+/23632
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Ie9040c6b127c268878a0845ed73d0918ec6bbb08
Gerrit-Change-Number: 23632
Gerrit-PatchSet: 12
Gerrit-Owner: Falkenber9 <robert.falkenberg at tu-dortmund.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210411/3fb695cf/attachment.htm>


More information about the gerrit-log mailing list