blob: c7be4a0eb7fb365cc90a4edb8f58d97ebb9dad7b [file] [log] [blame]
Sylvain Munaut76504e02010-12-07 00:24:32 +01001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4""" pySim: PCSC reader transport link
5"""
6
7#
8# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
9# Copyright (C) 2010 Harald Welte <laforge@gnumonks.org>
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation, either version 2 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program. If not, see <http://www.gnu.org/licenses/>.
23#
24
25from smartcard.Exceptions import NoCardException
26from smartcard.System import readers
27from smartcard.CardConnectionObserver import ConsoleCardConnectionObserver
28
29from pySim.exceptions import NoCardError
30from pySim.utils import h2i, i2h
31
32
33class PcscSimLink(object):
34
35 def __init__(self, reader_number=0, observer=0):
36 r = readers();
37 try:
38 self._con = r[reader_number].createConnection()
39 if (observer):
40 observer = ConsoleCardConnectionObserver()
41 self._con.addObserver(observer)
42 self._con.connect()
43 #print r[reader_number], b2h(self._con.getATR())
44 except NoCardException:
45 raise NoCardError()
46
47 def __del__(self):
48 self._con.disconnect()
49 return
50
51 def reset_card(self):
52 self._con.disconnect()
53 try:
54 self._con.connect()
55 except NoCardException:
56 raise NoCardError()
57 return 1
58
59 def send_apdu_raw(self, pdu):
60 """send_apdu_raw(pdu): Sends an APDU with minimal processing
61
62 pdu : string of hexadecimal characters (ex. "A0A40000023F00")
63 return : tuple(data, sw), where
64 data : string (in hex) of returned data (ex. "074F4EFFFF")
65 sw : string (in hex) of status word (ex. "9000")
66 """
67 apdu = h2i(pdu)
68
69 data, sw1, sw2 = self._con.transmit(apdu)
70
71 sw = [sw1, sw2]
72
73 # Return value
74 return i2h(data), i2h(sw)
75
76 def send_apdu(self, pdu):
77 """send_apdu(pdu): Sends an APDU and auto fetch response data
78
79 pdu : string of hexadecimal characters (ex. "A0A40000023F00")
80 return : tuple(data, sw), where
81 data : string (in hex) of returned data (ex. "074F4EFFFF")
82 sw : string (in hex) of status word (ex. "9000")
83 """
84 data, sw = self.send_apdu_raw(pdu)
85
86 if (sw is not None) and (sw[0:2] == '9f'):
87 pdu_gr = pdu[0:2] + 'c00000' + sw[2:4]
88 data, sw = self.send_apdu_raw(pdu_gr)
89
90 return data, sw
91
92 def send_apdu_checksw(self, pdu, sw="9000"):
93 """send_apdu_checksw(pdu,sw): Sends an APDU and check returned SW
94
95 pdu : string of hexadecimal characters (ex. "A0A40000023F00")
96 sw : string of 4 hexadecimal characters (ex. "9000")
97 return : tuple(data, sw), where
98 data : string (in hex) of returned data (ex. "074F4EFFFF")
99 sw : string (in hex) of status word (ex. "9000")
100 """
101 rv = self.send_apdu(pdu)
102 if sw.lower() != rv[1]:
103 raise RuntimeError("SW match failed ! Expected %s and got %s." % (sw.lower(), rv[1]))
104 return rv