Files
pysim/pySim/transport/__init__.py
Harald Welte e79cc8069a introduce SwMatchError exception
This allows callers further up the stack to catch the exception and
interpret it in some way (like decoding the number of remaining tries
in case of authentication errors)

Change-Id: Ia59962978745aef7038f750fa23f8dfc820645f4
2021-03-02 08:06:13 +01:00

107 lines
3.4 KiB
Python

# -*- coding: utf-8 -*-
""" pySim: PCSC reader transport link base
"""
from pySim.exceptions import *
#
# 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)
# When whe have sent the first APDU, the SW may indicate that there are response bytes
# available. There are two SWs commonly used for this 9fxx (sim) and 61xx (usim), where
# xx is the number of response bytes available.
# See also:
# SW1=9F: 3GPP TS 51.011 9.4.1, Responses to commands which are correctly executed
# SW1=61: ISO/IEC 7816-4, Table 5 — General meaning of the interindustry values of SW1-SW2
if (sw is not None) and ((sw[0:2] == '9f') or (sw[0:2] == '61')):
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 SwMatchError(rv[1], sw.lower())
return rv