Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 3 | # Code ported from simtrace host program apdu_split.c |
| 4 | # |
| 5 | # (C) 2010 by Harald Welte <hwelte@hmw-consulting.de> |
| 6 | # |
| 7 | # This program is free software; you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License version 2 |
| 9 | # as published by the Free Software Foundation |
| 10 | # |
| 11 | # This program is distributed in the hope that it will be useful, |
| 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | # GNU General Public License for more details. |
| 15 | |
| 16 | from enum import Enum |
| 17 | |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 18 | class apdu_states(Enum): |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 19 | APDU_S_CLA = 1 |
| 20 | APDU_S_INS = 2 |
| 21 | APDU_S_P1 = 3 |
| 22 | APDU_S_P2 = 4 |
| 23 | APDU_S_P3 = 5 |
| 24 | APDU_S_DATA = 6 |
| 25 | APDU_S_DATA_SINGLE = 7 |
| 26 | APDU_S_SW1 = 8 |
| 27 | APDU_S_SW2 = 9 |
| 28 | APDU_S_FIN = 10 |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 29 | |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 30 | |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 31 | class Apdu_splitter: |
| 32 | |
| 33 | def __init__(self): |
| 34 | self.state = apdu_states.APDU_S_CLA |
| 35 | self.buf = [] |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 36 | |
| 37 | def func_APDU_S_INS(self, c): |
| 38 | self.ins = c |
| 39 | |
| 40 | def func_APDU_S_CLA_P1_P2(self, c): |
| 41 | self.buf.append(c) |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 42 | self.state = apdu_states(self.state.value + 1) |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 43 | |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 44 | def func_APDU_S_P3(self, c): |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 45 | self.buf.append(c) |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 46 | self.data_remaining = 256 if c == 0 else c |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 47 | self.state = apdu_states.APDU_S_SW1 |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 48 | |
| 49 | def func_APDU_S_DATA(self, c): |
| 50 | self.buf.append(c) |
| 51 | self.data_remaining -= 1 |
| 52 | if data_remaining == 0: |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 53 | self.state = apdu_states.APDU_S_SW1; |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 54 | |
| 55 | def func_APDU_S_DATA_SINGLE(self, c): |
| 56 | self.buf.append(c) |
| 57 | self.data_remaining -= 1 |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 58 | self.state = apdu_states.APDU_S_SW1 |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 59 | |
| 60 | def func_APDU_S_SW1(self, c): |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 61 | if (c == 0x60): |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 62 | print("APDU_S_SW1: NULL") |
| 63 | else: |
| 64 | # check for 'all remaining' type ACK |
| 65 | if c == self.ins or c == self.ins + 1 or c == ~(self.ins+1): |
| 66 | print("ACK") |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 67 | self.state = apdu_states.APDU_S_DATA |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 68 | else: |
| 69 | # check for 'only next byte' type ACK */ |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 70 | if c == ~(self.ins): |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 71 | self.state = apdu_states.APDU_S_DATA_SINGLE |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 72 | else: |
| 73 | # must be SW1 |
| 74 | self.buf.append(c) |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 75 | self.state = apdu_states.APDU_S_SW2 |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 76 | |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 77 | def func_APDU_S_SW2(self, c): |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 78 | self.buf.append(c) |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 79 | print("APDU:", self.buf) |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 80 | self.state = apdu_states.APDU_S_FIN |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 81 | |
| 82 | Apdu_S = { |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 83 | apdu_states.APDU_S_CLA : func_APDU_S_CLA_P1_P2, |
| 84 | apdu_states.APDU_S_INS : func_APDU_S_INS, |
| 85 | apdu_states.APDU_S_P1 : func_APDU_S_CLA_P1_P2, |
| 86 | apdu_states.APDU_S_P2 : func_APDU_S_CLA_P1_P2, |
| 87 | apdu_states.APDU_S_P3 : func_APDU_S_P3, |
| 88 | apdu_states.APDU_S_DATA : func_APDU_S_DATA, |
| 89 | apdu_states.APDU_S_DATA_SINGLE : func_APDU_S_DATA_SINGLE, |
| 90 | apdu_states.APDU_S_SW1 : func_APDU_S_SW1, |
| 91 | apdu_states.APDU_S_SW2 : func_APDU_S_SW2 } |
| 92 | |
| 93 | def split(self, c): |
| 94 | self.Apdu_S[self.state](self, c) |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 95 | |
| 96 | |
| 97 | if __name__ == '__main__': |
| 98 | msg = [0xA0, 0xA4, 0x00, 0x00, 0x02] |
| 99 | apdus = Apdu_splitter() |
| 100 | |
| 101 | for c in msg: |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame^] | 102 | print(hex(c)) |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 103 | apdus.split(c) |
| 104 | |
| 105 | |