mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-16 18:38:32 +03:00
sysmo-usim-sjs1 requires P2 to be set to 0x0C (request FCI) when using the USIM application commands. The FCI is not used by pysim anyway and might even cause problems with other cards. This commit adds a pair of get/set methods to the SimCardCommands class in order to set a default for the selection control parameters (P1, P2). (Similar to the set/get methods for the class byte) The SysmoUSIMSJS1 class now calls the setter method for the selection control parameters inside of its constructuor and sets the selection control parameter default to "000C". This way we can be sure that we only change the behaviour for sysmo-usim-sjs1 and do not break support for any other cards. Change-Id: I1993a267c952bf37d5de1cb4e1107f445614c17b
112 lines
3.3 KiB
Python
112 lines
3.3 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
""" pySim: SIM Card commands according to ISO 7816-4 and TS 11.11
|
|
"""
|
|
|
|
#
|
|
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
|
|
# Copyright (C) 2010 Harald Welte <laforge@gnumonks.org>
|
|
#
|
|
# 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/>.
|
|
#
|
|
|
|
from pySim.utils import rpad, b2h
|
|
|
|
|
|
class SimCardCommands(object):
|
|
def __init__(self, transport):
|
|
self._tp = transport;
|
|
self._cla_byte = "a0"
|
|
self.sel_ctrl = "0000"
|
|
|
|
@property
|
|
def cla_byte(self):
|
|
return self._cla_byte
|
|
@cla_byte.setter
|
|
def cla_byte(self, value):
|
|
self._cla_byte = value
|
|
|
|
@property
|
|
def sel_ctrl(self):
|
|
return self._sel_ctrl
|
|
@sel_ctrl.setter
|
|
def sel_ctrl(self, value):
|
|
self._sel_ctrl = value
|
|
|
|
def select_file(self, dir_list):
|
|
rv = []
|
|
for i in dir_list:
|
|
data, sw = self._tp.send_apdu_checksw(self.cla_byte + "a4" + self.sel_ctrl + "02" + i)
|
|
rv.append(data)
|
|
return rv
|
|
|
|
def read_binary(self, ef, length=None, offset=0):
|
|
if not hasattr(type(ef), '__iter__'):
|
|
ef = [ef]
|
|
r = self.select_file(ef)
|
|
if length is None:
|
|
length = int(r[-1][4:8], 16) - offset
|
|
pdu = self.cla_byte + 'b0%04x%02x' % (offset, (min(256, length) & 0xff))
|
|
return self._tp.send_apdu(pdu)
|
|
|
|
def update_binary(self, ef, data, offset=0):
|
|
if not hasattr(type(ef), '__iter__'):
|
|
ef = [ef]
|
|
self.select_file(ef)
|
|
pdu = self.cla_byte + 'd6%04x%02x' % (offset, len(data)/2) + data
|
|
return self._tp.send_apdu_checksw(pdu)
|
|
|
|
def read_record(self, ef, rec_no):
|
|
if not hasattr(type(ef), '__iter__'):
|
|
ef = [ef]
|
|
r = self.select_file(ef)
|
|
rec_length = int(r[-1][28:30], 16)
|
|
pdu = self.cla_byte + 'b2%02x04%02x' % (rec_no, rec_length)
|
|
return self._tp.send_apdu(pdu)
|
|
|
|
def update_record(self, ef, rec_no, data, force_len=False):
|
|
if not hasattr(type(ef), '__iter__'):
|
|
ef = [ef]
|
|
r = self.select_file(ef)
|
|
if not force_len:
|
|
rec_length = int(r[-1][28:30], 16)
|
|
if (len(data)/2 != rec_length):
|
|
raise ValueError('Invalid data length (expected %d, got %d)' % (rec_length, len(data)/2))
|
|
else:
|
|
rec_length = len(data)/2
|
|
pdu = (self.cla_byte + 'dc%02x04%02x' % (rec_no, rec_length)) + data
|
|
return self._tp.send_apdu_checksw(pdu)
|
|
|
|
def record_size(self, ef):
|
|
r = self.select_file(ef)
|
|
return int(r[-1][28:30], 16)
|
|
|
|
def record_count(self, ef):
|
|
r = self.select_file(ef)
|
|
return int(r[-1][4:8], 16) // int(r[-1][28:30], 16)
|
|
|
|
def run_gsm(self, rand):
|
|
if len(rand) != 32:
|
|
raise ValueError('Invalid rand')
|
|
self.select_file(['3f00', '7f20'])
|
|
return self._tp.send_apdu(self.cla_byte + '88000010' + rand)
|
|
|
|
def reset_card(self):
|
|
return self._tp.reset_card()
|
|
|
|
def verify_chv(self, chv_no, code):
|
|
fc = rpad(b2h(code), 16)
|
|
return self._tp.send_apdu_checksw(self.cla_byte + '2000' + ('%02X' % chv_no) + '08' + fc)
|