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 | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 30 | class Apdu_splitter: |
| 31 | |
| 32 | def __init__(self): |
| 33 | self.state = apdu_states.APDU_S_CLA |
| 34 | self.buf = [] |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 35 | |
| 36 | def func_APDU_S_INS(self, c): |
| 37 | self.ins = c |
Christina Quast | 51925a6 | 2015-04-14 21:04:14 +0200 | [diff] [blame] | 38 | self.buf.append(c) |
| 39 | self.state = apdu_states(self.state.value + 1) |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 40 | |
| 41 | def func_APDU_S_CLA_P1_P2(self, c): |
| 42 | self.buf.append(c) |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 43 | self.state = apdu_states(self.state.value + 1) |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 44 | |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 45 | def func_APDU_S_P3(self, c): |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 46 | self.buf.append(c) |
Christina Quast | 51925a6 | 2015-04-14 21:04:14 +0200 | [diff] [blame] | 47 | self.data_remaining = 256 if c == 0 else c |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 48 | self.state = apdu_states.APDU_S_SW1 |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 49 | |
| 50 | def func_APDU_S_DATA(self, c): |
| 51 | self.buf.append(c) |
Christina Quast | 9547e9f | 2015-04-14 22:18:30 +0200 | [diff] [blame^] | 52 | self.data.append(c) |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 53 | self.data_remaining -= 1 |
Christina Quast | 51925a6 | 2015-04-14 21:04:14 +0200 | [diff] [blame] | 54 | if self.data_remaining == 0: |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 55 | self.state = apdu_states.APDU_S_SW1; |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 56 | |
| 57 | def func_APDU_S_DATA_SINGLE(self, c): |
| 58 | self.buf.append(c) |
| 59 | self.data_remaining -= 1 |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 60 | self.state = apdu_states.APDU_S_SW1 |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 61 | |
| 62 | def func_APDU_S_SW1(self, c): |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 63 | if (c == 0x60): |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 64 | print("APDU_S_SW1: NULL") |
| 65 | else: |
| 66 | # check for 'all remaining' type ACK |
| 67 | if c == self.ins or c == self.ins + 1 or c == ~(self.ins+1): |
| 68 | print("ACK") |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 69 | self.state = apdu_states.APDU_S_DATA |
Christina Quast | 9547e9f | 2015-04-14 22:18:30 +0200 | [diff] [blame^] | 70 | self.data = [] |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 71 | else: |
| 72 | # check for 'only next byte' type ACK */ |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 73 | if c == ~(self.ins): |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 74 | self.state = apdu_states.APDU_S_DATA_SINGLE |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 75 | else: |
| 76 | # must be SW1 |
Christina Quast | 9547e9f | 2015-04-14 22:18:30 +0200 | [diff] [blame^] | 77 | self.sw1 = c |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 78 | self.buf.append(c) |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 79 | self.state = apdu_states.APDU_S_SW2 |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 80 | |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 81 | def func_APDU_S_SW2(self, c): |
Christina Quast | 79c2a3a | 2015-04-14 14:55:13 +0200 | [diff] [blame] | 82 | self.buf.append(c) |
Christina Quast | 9547e9f | 2015-04-14 22:18:30 +0200 | [diff] [blame^] | 83 | self.sw2 = c |
Christina Quast | 51925a6 | 2015-04-14 21:04:14 +0200 | [diff] [blame] | 84 | print("APDU:", hex(self.ins), ' '.join(hex(x) for x in self.buf)) |
Christina Quast | 9547e9f | 2015-04-14 22:18:30 +0200 | [diff] [blame^] | 85 | self.state = apdu_states.APDU_S_FIN |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 86 | |
| 87 | Apdu_S = { |
Christina Quast | d4c8b51 | 2015-04-14 15:53:13 +0200 | [diff] [blame] | 88 | apdu_states.APDU_S_CLA : func_APDU_S_CLA_P1_P2, |
| 89 | apdu_states.APDU_S_INS : func_APDU_S_INS, |
| 90 | apdu_states.APDU_S_P1 : func_APDU_S_CLA_P1_P2, |
| 91 | apdu_states.APDU_S_P2 : func_APDU_S_CLA_P1_P2, |
| 92 | apdu_states.APDU_S_P3 : func_APDU_S_P3, |
| 93 | apdu_states.APDU_S_DATA : func_APDU_S_DATA, |
| 94 | apdu_states.APDU_S_DATA_SINGLE : func_APDU_S_DATA_SINGLE, |
| 95 | apdu_states.APDU_S_SW1 : func_APDU_S_SW1, |
| 96 | apdu_states.APDU_S_SW2 : func_APDU_S_SW2 } |
| 97 | |
| 98 | def split(self, c): |
| 99 | self.Apdu_S[self.state](self, c) |
Christina Quast | e64aa5b | 2015-04-14 15:07:33 +0200 | [diff] [blame] | 100 | |
| 101 | |
| 102 | if __name__ == '__main__': |
Christina Quast | 51925a6 | 2015-04-14 21:04:14 +0200 | [diff] [blame] | 103 | msg1 = [0xA0, 0xA4, 0x00, 0x00, 0x02, 0xA4, 0x7F, 0x20, 0x9F, 0x16] |
| 104 | msg2 = [0xA0, 0xC0, 0x00, 0x00, 0x16, 0xC0, |
| 105 | 0x00, 0x00, 0x00, 0x00, 0x7F, 0x20, |
| 106 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 107 | 0x09, 0x91, 0x00, 0x17, 0x04, 0x00, 0x00, 0x00, |
| 108 | 0x83, 0x8A, 0x90, 0x00] |
Christina Quast | 9547e9f | 2015-04-14 22:18:30 +0200 | [diff] [blame^] | 109 | apdus = [] |
| 110 | apdu = Apdu_splitter() |
Christina Quast | 51925a6 | 2015-04-14 21:04:14 +0200 | [diff] [blame] | 111 | for c in msg2 + msg1: |
Christina Quast | 9547e9f | 2015-04-14 22:18:30 +0200 | [diff] [blame^] | 112 | apdu.split(c) |
| 113 | if apdu.state == apdu_states.APDU_S_FIN: |
| 114 | apdus.append(apdu) |
| 115 | apdu = Apdu_splitter() |
| 116 | for a in apdus: |
| 117 | print(' '.join(hex(x) for x in a.buf)) |