Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | from smartcard.scard import * |
| 4 | import smartcard.util |
| 5 | |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 6 | import array |
Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 7 | |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 8 | from util import HEX |
| 9 | |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 10 | class SmartcardException(Exception): |
| 11 | pass |
Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 12 | |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 13 | class SmartcardConnection: |
| 14 | # hcard, dwActiveProtocol, hcontext, reader |
Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 15 | |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 16 | def __init__(self): |
| 17 | self.establish_context() |
| 18 | self.connect_card() |
Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 19 | |
Christina Quast | 5163624 | 2015-04-06 00:44:50 +0200 | [diff] [blame] | 20 | def getATR(self): |
| 21 | hresult, reader, state, protocol, atr = SCardStatus(self.hcard) |
| 22 | if hresult != SCARD_S_SUCCESS: |
| 23 | print 'failed to get status: ' + SCardGetErrorMessage(hresult) |
| 24 | print 'Reader:', reader |
| 25 | print 'State:', state |
| 26 | print 'Protocol:', protocol |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 27 | print 'ATR:', HEX(atr) |
Christina Quast | 7741f71 | 2015-04-06 19:06:05 +0200 | [diff] [blame] | 28 | return array.array('B', atr) |
| 29 | |
| 30 | def reset_card(self): |
| 31 | hresult, self.dwActiveProtocol = SCardReconnect(self.hcard, SCARD_SHARE_SHARED, |
| 32 | SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD) |
| 33 | if hresult != SCARD_S_SUCCESS: |
| 34 | raise SmartcardException('Unable to retrieve Atr: ' + |
| 35 | SCardGetErrorMessage(hresult)) |
Christina Quast | 5163624 | 2015-04-06 00:44:50 +0200 | [diff] [blame] | 36 | |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 37 | def connect_card(self): |
| 38 | hresult, self.hcard, self.dwActiveProtocol = SCardConnect(self.hcontext, self.reader, |
| 39 | SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) |
| 40 | if hresult != SCARD_S_SUCCESS: |
| 41 | raise SmartcardException('Unable to connect: ' + |
Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 42 | SCardGetErrorMessage(hresult)) |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 43 | print 'Connected with active protocol', self.dwActiveProtocol |
Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 44 | |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 45 | def establish_context(self): |
| 46 | hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) |
| 47 | if hresult != SCARD_S_SUCCESS: |
| 48 | raise SmartcardException('Failed to establish context : ' + |
| 49 | SCardGetErrorMessage(hresult)) |
| 50 | print 'Context established!' |
Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 51 | |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 52 | hresult, readers = SCardListReaders(self.hcontext, []) |
| 53 | if hresult != SCARD_S_SUCCESS: |
| 54 | raise SmartcardException('Failed to list readers: ' + |
| 55 | SCardGetErrorMessage(hresult)) |
| 56 | print 'PCSC Readers:', readers |
| 57 | |
| 58 | if len(readers) < 1: |
| 59 | raise SmartcardException('No smart card readers') |
| 60 | |
| 61 | self.reader = readers[0] |
| 62 | print "Using reader:", self.reader |
| 63 | |
| 64 | def release_context(self): |
| 65 | hresult = SCardReleaseContext(self.hcontext) |
| 66 | if hresult != SCARD_S_SUCCESS: |
| 67 | raise SmartcardException('Failed to release context: ' + |
| 68 | SCardGetErrorMessage(hresult)) |
| 69 | print 'Released context.' |
| 70 | |
| 71 | def send_receive_cmd(self, cmd): |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 72 | print("Cmd to SIM: " + HEX(cmd)) |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 73 | hresult, resp = SCardTransmit(self.hcard, self.dwActiveProtocol, |
| 74 | cmd.tolist()) |
| 75 | if hresult != SCARD_S_SUCCESS: |
| 76 | raise SmartcardException('Failed to transmit: ' + |
| 77 | SCardGetErrorMessage(hresult)) |
Christina Quast | f2e53f0 | 2015-04-11 08:42:38 +0200 | [diff] [blame] | 78 | print 'SIM Ans: ' + HEX(resp) |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 79 | return array.array('B', resp) |
| 80 | |
| 81 | def disconnect_card(self): |
| 82 | hresult = SCardDisconnect(self.hcard, SCARD_UNPOWER_CARD) |
| 83 | if hresult != SCARD_S_SUCCESS: |
| 84 | raise SmartcardException('Failed to disconnect: ' + |
| 85 | SCardGetErrorMessage(hresult)) |
| 86 | print 'Disconnected' |
Christina Quast | 254acae | 2015-04-01 19:36:34 +0200 | [diff] [blame] | 87 | |
| 88 | |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 89 | def close(self): |
| 90 | self.disconnect_card() |
| 91 | self.release_context() |
Christina Quast | 097b218 | 2015-04-05 10:21:11 +0200 | [diff] [blame] | 92 | |
| 93 | |
| 94 | if __name__ == '__main__': |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 95 | import constants |
| 96 | |
| 97 | sm_con = SmartcardConnection() |
Christina Quast | 5163624 | 2015-04-06 00:44:50 +0200 | [diff] [blame] | 98 | sm_con.getATR() |
Christina Quast | 5149cd6 | 2015-04-06 00:33:52 +0200 | [diff] [blame] | 99 | print(sm_con.send_receive_cmd(constants.CMD_SEL_ROOT)) |
| 100 | print(sm_con.send_receive_cmd(constants.CMD_SEL_FILE)) |
| 101 | print(sm_con.send_receive_cmd(constants.CMD_GET_DATA)) |
| 102 | sm_con.close() |