mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-17 10:58:34 +03:00
The method send_apdu_checksw() is used to check the SW of the final response against some pre defined value. However, in many cases the last two digits of the SW are used to return varying information (e.g. length information or a more specific status info). To cover those cases it would be helfpul to define status words that contain wildcards (e.g. 61**) in order to be able to accept all SWs from 6100 to 61ff. - When the user supplies an expected SW with wildcards, mask out those digits in the response before comparing Change-Id: I5bfc0522b4228b5d9b3415f6e708abcf0da0a7b7
100 lines
3.1 KiB
Python
100 lines
3.1 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
""" pySim: PCSC reader transport link base
|
|
"""
|
|
|
|
#
|
|
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
|
|
#
|
|
# 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/>.
|
|
#
|
|
|
|
class LinkBase(object):
|
|
|
|
def wait_for_card(self, timeout=None, newcardonly=False):
|
|
"""wait_for_card(): Wait for a card and connect to it
|
|
|
|
timeout : Maximum wait time (None=no timeout)
|
|
newcardonly : Should we wait for a new card, or an already
|
|
inserted one ?
|
|
"""
|
|
pass
|
|
|
|
def connect(self):
|
|
"""connect(): Connect to a card immediately
|
|
"""
|
|
pass
|
|
|
|
def disconnect(self):
|
|
"""disconnect(): Disconnect from card
|
|
"""
|
|
pass
|
|
|
|
def reset_card(self):
|
|
"""reset_card(): Resets the card (power down/up)
|
|
"""
|
|
pass
|
|
|
|
def send_apdu_raw(self, pdu):
|
|
"""send_apdu_raw(pdu): Sends an APDU with minimal processing
|
|
|
|
pdu : string of hexadecimal characters (ex. "A0A40000023F00")
|
|
return : tuple(data, sw), where
|
|
data : string (in hex) of returned data (ex. "074F4EFFFF")
|
|
sw : string (in hex) of status word (ex. "9000")
|
|
"""
|
|
pass
|
|
|
|
def send_apdu(self, pdu):
|
|
"""send_apdu(pdu): Sends an APDU and auto fetch response data
|
|
|
|
pdu : string of hexadecimal characters (ex. "A0A40000023F00")
|
|
return : tuple(data, sw), where
|
|
data : string (in hex) of returned data (ex. "074F4EFFFF")
|
|
sw : string (in hex) of status word (ex. "9000")
|
|
"""
|
|
data, sw = self.send_apdu_raw(pdu)
|
|
|
|
if (sw is not None) and (sw[0:2] == '9f'):
|
|
pdu_gr = pdu[0:2] + 'c00000' + sw[2:4]
|
|
data, sw = self.send_apdu_raw(pdu_gr)
|
|
|
|
return data, sw
|
|
|
|
def send_apdu_checksw(self, pdu, sw="9000"):
|
|
"""send_apdu_checksw(pdu,sw): Sends an APDU and check returned SW
|
|
|
|
pdu : string of hexadecimal characters (ex. "A0A40000023F00")
|
|
sw : string of 4 hexadecimal characters (ex. "9000"). The
|
|
user may mask out certain digits using a '?' to add some
|
|
ambiguity if needed.
|
|
return : tuple(data, sw), where
|
|
data : string (in hex) of returned data (ex. "074F4EFFFF")
|
|
sw : string (in hex) of status word (ex. "9000")
|
|
"""
|
|
rv = self.send_apdu(pdu)
|
|
|
|
# Create a masked version of the returned status word
|
|
sw_masked = ""
|
|
for i in range(0, 4):
|
|
if sw.lower()[i] == '?':
|
|
sw_masked = sw_masked + '?'
|
|
else:
|
|
sw_masked = sw_masked + rv[1][i].lower()
|
|
|
|
if sw.lower() != sw_masked:
|
|
raise RuntimeError("SW match failed ! Expected %s and got %s." % (sw.lower(), rv[1]))
|
|
return rv
|