Change in pysim[master]: pySim-shell: complete CHV/PIN management tools

laforge gerrit-no-reply at lists.osmocom.org
Fri Apr 2 14:44:46 UTC 2021


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

Change subject: pySim-shell: complete CHV/PIN management tools
......................................................................

pySim-shell: complete CHV/PIN management tools

At the moment we only have a basic version of a verify_chv commnad, but
in order to handle any CHV/PIN related situation we also need commands
to enable, disable, change and unblock CHV.

- fix verify_chv commnad: more distinct parameter names, better help
  strings, correct pin code encoding and add external source lookup
- Add unblock_chv, change_chv, enable_chv and disable_chv commands
- add/fix related functions in commands.py

Change-Id: Ic89446e6bd2021095e579fb6b20458df48ba6413
Related: OS#4963
---
M pySim-shell.py
M pySim/card_data.py
M pySim/commands.py
3 files changed, 108 insertions(+), 13 deletions(-)

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



diff --git a/pySim-shell.py b/pySim-shell.py
index 68896cb..11953eb 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -39,7 +39,7 @@
 from pySim.commands import SimCardCommands
 from pySim.cards import card_detect, Card
 from pySim.utils import h2b, swap_nibbles, rpad, h2s
-from pySim.utils import dec_st, init_reader, sanitize_pin_adm, tabulate_str_list
+from pySim.utils import dec_st, init_reader, sanitize_pin_adm, tabulate_str_list, is_hex
 from pySim.card_handler import card_handler
 
 from pySim.filesystem import CardMF, RuntimeState, CardDF, CardADF
@@ -141,15 +141,79 @@
 		index_dict = { 1: self._cmd.rs.selected_file.get_selectable_names() }
 		return self._cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict)
 
+	def get_code(self, code):
+		"""Use code either directly or try to get it from external data source"""
+		auto = ('PIN1', 'PIN2', 'PUK1', 'PUK2')
+
+		if str(code).upper() not in auto:
+			return sanitize_pin_adm(code)
+
+		result = card_data_get_field(str(code), key='ICCID', value=self._cmd.iccid)
+		result = sanitize_pin_adm(result)
+		if result:
+			self._cmd.poutput("found %s '%s' for ICCID '%s'" % (code.upper(), result, self._cmd.iccid))
+		else:
+			self._cmd.poutput("cannot find %s for ICCID '%s'" % (code.upper(), self._cmd.iccid))
+		return result
+
 	verify_chv_parser = argparse.ArgumentParser()
-	verify_chv_parser.add_argument('--chv-nr', type=int, default=1, help='CHV Number')
-	verify_chv_parser.add_argument('code', help='CODE/PIN/PUK')
+	verify_chv_parser.add_argument('--pin-nr', type=int, default=1, help='PIN Number, 1=PIN1, 2=PIN2 or custom value (decimal)')
+	verify_chv_parser.add_argument('pin_code', type=str, help='PIN code digits, \"PIN1\" or \"PIN2\" to get PIN code from external data source')
 
 	@cmd2.with_argparser(verify_chv_parser)
 	def do_verify_chv(self, opts):
-		"""Verify (authenticate) using specified CHV (PIN)"""
-		(data, sw) = self._cmd.card._scc.verify_chv(opts.chv_nr, opts.code)
-		self._cmd.poutput(data)
+		"""Verify (authenticate) using specified PIN code"""
+		pin = self.get_code(opts.pin_code)
+		(data, sw) = self._cmd.card._scc.verify_chv(opts.pin_nr, h2b(pin))
+		self._cmd.poutput("CHV verfication successful")
+
+	unblock_chv_parser = argparse.ArgumentParser()
+	unblock_chv_parser.add_argument('--pin-nr', type=int, default=1, help='PUK Number, 1=PIN1, 2=PIN2 or custom value (decimal)')
+	unblock_chv_parser.add_argument('puk_code', type=str, help='PUK code digits \"PUK1\" or \"PUK2\" to get PUK code from external data source')
+	unblock_chv_parser.add_argument('new_pin_code', type=str, help='PIN code digits \"PIN1\" or \"PIN2\" to get PIN code from external data source')
+
+	@cmd2.with_argparser(unblock_chv_parser)
+	def do_unblock_chv(self, opts):
+		"""Unblock PIN code using specified PUK code"""
+		new_pin = self.get_code(opts.new_pin_code)
+		puk = self.get_code(opts.puk_code)
+		(data, sw) = self._cmd.card._scc.unblock_chv(opts.pin_nr, h2b(puk), h2b(new_pin))
+		self._cmd.poutput("CHV unblock successful")
+
+	change_chv_parser = argparse.ArgumentParser()
+	change_chv_parser.add_argument('--pin-nr', type=int, default=1, help='PUK Number, 1=PIN1, 2=PIN2 or custom value (decimal)')
+	change_chv_parser.add_argument('pin_code', type=str, help='PIN code digits \"PIN1\" or \"PIN2\" to get PIN code from external data source')
+	change_chv_parser.add_argument('new_pin_code', type=str, help='PIN code digits \"PIN1\" or \"PIN2\" to get PIN code from external data source')
+
+	@cmd2.with_argparser(change_chv_parser)
+	def do_change_chv(self, opts):
+		"""Change PIN code to a new PIN code"""
+		new_pin = self.get_code(opts.new_pin_code)
+		pin = self.get_code(opts.pin_code)
+		(data, sw) = self._cmd.card._scc.change_chv(opts.pin_nr, h2b(pin), h2b(new_pin))
+		self._cmd.poutput("CHV change successful")
+
+	disable_chv_parser = argparse.ArgumentParser()
+	disable_chv_parser.add_argument('--pin-nr', type=int, default=1, help='PIN Number, 1=PIN1, 2=PIN2 or custom value (decimal)')
+	disable_chv_parser.add_argument('pin_code', type=str, help='PIN code digits, \"PIN1\" or \"PIN2\" to get PIN code from external data source')
+
+	@cmd2.with_argparser(disable_chv_parser)
+	def do_disable_chv(self, opts):
+		"""Disable PIN code using specified PIN code"""
+		pin = self.get_code(opts.pin_code)
+		(data, sw) = self._cmd.card._scc.disable_chv(opts.pin_nr, h2b(pin))
+		self._cmd.poutput("CHV disable successful")
+
+	enable_chv_parser = argparse.ArgumentParser()
+	enable_chv_parser.add_argument('--pin-nr', type=int, default=1, help='PIN Number, 1=PIN1, 2=PIN2 or custom value (decimal)')
+	enable_chv_parser.add_argument('pin_code', type=str, help='PIN code digits, \"PIN1\" or \"PIN2\" to get PIN code from external data source')
+
+	@cmd2.with_argparser(enable_chv_parser)
+	def do_enable_chv(self, opts):
+		"""Enable PIN code using specified PIN code"""
+		pin = self.get_code(opts.pin_code)
+		(data, sw) = self._cmd.card._scc.enable_chv(opts.pin_nr, h2b(pin))
+		self._cmd.poutput("CHV enable successful")
 
 	dir_parser = argparse.ArgumentParser()
 	dir_parser.add_argument('--fids', help='Show file identifiers', action='store_true')
diff --git a/pySim/card_data.py b/pySim/card_data.py
index 495c1f3..ebc63a6 100644
--- a/pySim/card_data.py
+++ b/pySim/card_data.py
@@ -26,7 +26,7 @@
 
 class CardData(object):
 
-	VALID_FIELD_NAMES = ['ICCID', 'ADM1', 'IMSI']
+	VALID_FIELD_NAMES = ['ICCID', 'ADM1', 'IMSI', 'PIN1', 'PIN2', 'PUK1', 'PUK2']
 
 	# check input parameters, but do nothing concrete yet
 	def get_data(self, fields=[], key='ICCID', value=""):
diff --git a/pySim/commands.py b/pySim/commands.py
index 65c3891..5184a77 100644
--- a/pySim/commands.py
+++ b/pySim/commands.py
@@ -21,7 +21,8 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-from pySim.utils import rpad, b2h
+from pySim.utils import rpad, b2h, sw_match
+from pySim.exceptions import SwMatchError
 
 class SimCardCommands(object):
 	def __init__(self, transport):
@@ -219,9 +220,39 @@
 	def reset_card(self):
 		return self._tp.reset_card()
 
-	def verify_chv(self, chv_no, code):
-		fc = rpad(b2h(code), 16)
+	def _chv_process_sw(self, op_name, chv_no, pin_code, sw):
+		if sw_match(sw, '63cx'):
+			raise RuntimeError('Failed to %s chv_no 0x%02X with code 0x%s, %i tries left.' %
+							   (op_name, chv_no, b2h(pin_code).upper(), int(sw[3])))
+		elif (sw != '9000'):
+			raise SwMatchError(sw, '9000')
+
+	def verify_chv(self, chv_no, pin_code):
+		fc = rpad(b2h(pin_code), 16)
 		data, sw = self._tp.send_apdu(self.cla_byte + '2000' + ('%02X' % chv_no) + '08' + fc)
-		if (sw != '9000'):
-			raise RuntimeError('Failed to authenticate with ADM key %s, %i tries left.' % (code, int(sw[3])))
-		return (data,sw)
+		self._chv_process_sw('verify', chv_no, pin_code, sw)
+		return (data, sw)
+
+	def unblock_chv(self, chv_no, puk_code, pin_code):
+		fc = rpad(b2h(puk_code), 16) + rpad(b2h(pin_code), 16)
+		data, sw = self._tp.send_apdu(self.cla_byte + '2C00' + ('%02X' % chv_no) + '10' + fc)
+		self._chv_process_sw('unblock', chv_no, pin_code, sw)
+		return (data, sw)
+
+	def change_chv(self, chv_no, pin_code, new_pin_code):
+		fc = rpad(b2h(pin_code), 16) + rpad(b2h(new_pin_code), 16)
+		data, sw = self._tp.send_apdu(self.cla_byte + '2400' + ('%02X' % chv_no) + '10' + fc)
+		self._chv_process_sw('change', chv_no, pin_code, sw)
+		return (data, sw)
+
+	def disable_chv(self, chv_no, pin_code):
+		fc = rpad(b2h(pin_code), 16)
+		data, sw = self._tp.send_apdu(self.cla_byte + '2600' + ('%02X' % chv_no) + '08' + fc)
+		self._chv_process_sw('disable', chv_no, pin_code, sw)
+		return (data, sw)
+
+	def enable_chv(self, chv_no, pin_code):
+		fc = rpad(b2h(pin_code), 16)
+		data, sw = self._tp.send_apdu(self.cla_byte + '2800' + ('%02X' % chv_no) + '08' + fc)
+		self._chv_process_sw('enable', chv_no, pin_code, sw)
+		return (data, sw)

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

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Ic89446e6bd2021095e579fb6b20458df48ba6413
Gerrit-Change-Number: 23541
Gerrit-PatchSet: 6
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-CC: fixeria <vyanitskiy at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210402/412c92ac/attachment.htm>


More information about the gerrit-log mailing list