[PATCH] pysim[master]: cards: Add Fairwaves SIM implementation.

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Alexander Chemeris gerrit-no-reply at lists.osmocom.org
Wed Jan 10 05:19:24 UTC 2018


Review at  https://gerrit.osmocom.org/5722

cards: Add Fairwaves SIM implementation.

Change-Id: Ia10ac433d3b0482bdf727c31f65a10042152797b
---
M pySim/cards.py
1 file changed, 145 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/22/5722/1

diff --git a/pySim/cards.py b/pySim/cards.py
index 046766e..b1b70be 100644
--- a/pySim/cards.py
+++ b/pySim/cards.py
@@ -539,15 +539,158 @@
 		r = self._scc.select_file(['3f00', '7f10'])
 		data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 104), force_len=True)
 
+	def erase(self):
+		return
+
+
+class FairwavesSIM(Card):
+	"""
+	FairwavesSIM
+
+	The SIM card is operating according to the standard.
+	For Ki/OP/OPC programming the following files are additionally open for writing:
+		3F00/7F20/FF01 – OP/OPC:
+		byte 1 = 0x01, bytes 2-17: OPC;
+		byte 1 = 0x00, bytes 2-17: OP;
+		3F00/7F20/FF02: Ki
+	"""
+
+	name = 'Fairwaves SIM'
+	# Propriatary files
+	_EF_num = {
+	'Ki': 'FF02',
+	'OP/OPC': 'FF01',
+	}
+	_EF = {
+	'Ki':     DF['GSM']+[_EF_num['Ki']],
+	'OP/OPC': DF['GSM']+[_EF_num['OP/OPC']],
+	}
+
+	def __init__(self, ssc):
+		super(FairwavesSIM, self).__init__(ssc)
+		self._adm_chv_num = 0x11
+		self._adm2_chv_num = 0x12
+
+
+	@classmethod
+	def autodetect(kls, scc):
+		try:
+			# Look for ATR
+			if scc.get_atr() == toBytes("3B 9F 96 80 1F C7 80 31 A0 73 BE 21 13 67 44 22 06 10 00 00 01 A9"):
+				return kls(scc)
+		except:
+			return None
+		return None
+
+
+	def verify_adm2(self, key):
+		'''
+		Authenticate with ADM2 key.
+		
+		Fairwaves SIM cards support hierarchical key structure and ADM2 key
+		is a key which has access to proprietary files (Ki and OP/OPC).
+		That said, ADM key inherits permissions of ADM2 key and thus we rarely
+		need ADM2 key per se.
+		'''
+		(res, sw) = self._scc.verify_chv(self._adm2_chv_num, key)
+		return sw
+
+
+	def read_ki(self):
+		"""
+		Read Ki in proprietary file.
+
+		Requires ADM1 access level
+		"""
+		return self._scc.read_binary(self._EF['Ki'])
+
+
+	def update_ki(self, ki):
+		"""
+		Set Ki in proprietary file.
+
+		Requires ADM1 access level
+		"""
+		data, sw = self._scc.update_binary(self._EF['Ki'], ki)
+		return sw
+
+
+	def read_op_opc(self):
+		"""
+		Read Ki in proprietary file.
+
+		Requires ADM1 access level
+		"""
+		(ef, sw) = self._scc.read_binary(self._EF['OP/OPC'])
+		type = 'OP' if ef[0:2] == '00' else 'OPC'
+		return ((type, ef[2:]), sw)
+
+
+	def update_op(self, op):
+		"""
+		Set OP in proprietary file.
+
+		Requires ADM1 access level
+		"""
+		content = '00' + op
+		data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
+		return sw
+
+
+	def update_opc(self, opc):
+		"""
+		Set OPC in proprietary file.
+
+		Requires ADM1 access level
+		"""
+		content = '01' + opc
+		data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
+		return sw
+
+
+	def program(self, p):
+		# authenticate as ADM1
+		if not p['pin_adm']:
+			raise ValueError("Please provide a PIN-ADM as there is no default one")
+		sw = self.verify_adm(h2b(p['pin_adm']))
+		if sw != '9000':
+			raise RuntimeError('Failed to authenticate with ADM key %s'%(p['pin_adm'],))
+
+		# TODO: Set operator name
+		if p.get('smsp') is not None:
+			sw = self.update_smsp(p['smsp'])
+			if sw != '9000':
+				print("Programming SMSP failed with code %s"%sw)
+		# This SIM doesn't support changing ICCID
+		if p.get('mcc') is not None and p.get('mnc') is not None:
+			sw = self.update_hplmn_act(p['mcc'], p['mnc'])
+			if sw != '9000':
+				print("Programming MCC/MNC failed with code %s"%sw)
+		if p.get('imsi') is not None:
+			sw = self.update_imsi(p['imsi'])
+			if sw != '9000':
+				print("Programming IMSI failed with code %s"%sw)
+		if p.get('ki') is not None:
+			sw = self.update_ki(p['ki'])
+			if sw != '9000':
+				print("Programming Ki failed with code %s"%sw)
+		if p.get('opc') is not None:
+			sw = self.update_opc(p['opc'])
+			if sw != '9000':
+				print("Programming OPC failed with code %s"%sw)
+		if p.get('acc') is not None:
+			sw = self.update_acc(p['acc'])
+			if sw != '9000':
+				print("Programming ACC failed with code %s"%sw)
 
 	def erase(self):
 		return
 
 
-
 	# In order for autodetection ...
 _cards_classes = [ FakeMagicSim, SuperSim, MagicSim, GrcardSim,
-		   SysmoSIMgr1, SysmoSIMgr2, SysmoUSIMgr1, SysmoUSIMSJS1 ]
+		   SysmoSIMgr1, SysmoSIMgr2, SysmoUSIMgr1, SysmoUSIMSJS1,
+		   FairwavesSIM ]
 
 def card_autodetect(scc):
 	for kls in _cards_classes:

-- 
To view, visit https://gerrit.osmocom.org/5722
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia10ac433d3b0482bdf727c31f65a10042152797b
Gerrit-PatchSet: 1
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Owner: Alexander Chemeris <Alexander.Chemeris at gmail.com>



More information about the gerrit-log mailing list