blob: d2bb684790964fac859a8151ce774fa61ebffffc [file] [log] [blame]
Christina Quaste64aa5b2015-04-14 15:07:33 +02001#!/usr/bin/env python
2
Christina Quast79c2a3a2015-04-14 14:55:13 +02003# 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
16from enum import Enum
Christina Quastfb91bb72015-04-18 13:31:42 +020017from util import HEX
18from array import array
Christina Quast79c2a3a2015-04-14 14:55:13 +020019
Christina Quastd4c8b512015-04-14 15:53:13 +020020class apdu_states(Enum):
Christina Quaste64aa5b2015-04-14 15:07:33 +020021 APDU_S_CLA = 1
22 APDU_S_INS = 2
23 APDU_S_P1 = 3
24 APDU_S_P2 = 4
25 APDU_S_P3 = 5
Christina Quastfb91bb72015-04-18 13:31:42 +020026 APDU_S_SEND_DATA = 6
27 APDU_S_DATA = 7
28 APDU_S_DATA_SINGLE = 8
29 APDU_S_SW1 = 9
30 APDU_S_SW2 = 10
31 APDU_S_FIN = 11
Christina Quast0d98b9f2015-05-03 14:22:51 +020032 PTS = 12
Christina Quast79c2a3a2015-04-14 14:55:13 +020033
Christina Quastd4c8b512015-04-14 15:53:13 +020034class Apdu_splitter:
35
36 def __init__(self):
37 self.state = apdu_states.APDU_S_CLA
Christina Quast20e89af2015-05-14 16:55:35 +020038 self.buf = array('B', [])
39 self.pts_buf = array('B', [])
40 self.data = array('B', [])
Christina Quastfb91bb72015-04-18 13:31:42 +020041 self.ins = array('B', [])
42 self.data_remainig = 0
Christina Quast79c2a3a2015-04-14 14:55:13 +020043
44 def func_APDU_S_INS(self, c):
45 self.ins = c
Christina Quast51925a62015-04-14 21:04:14 +020046 self.buf.append(c)
47 self.state = apdu_states(self.state.value + 1)
Christina Quast79c2a3a2015-04-14 14:55:13 +020048
Christina Quast0d98b9f2015-05-03 14:22:51 +020049 def func_PTS(self, c):
50 self.pts_buf.append(c)
51 print("PTS: ", self.pts_buf)
52 if self.pts_buf == [0xff, 0x00, 0xff]:
53 self.state = apdu_states.APDU_S_FIN
54
Christina Quast79c2a3a2015-04-14 14:55:13 +020055 def func_APDU_S_CLA_P1_P2(self, c):
Christina Quast0d98b9f2015-05-03 14:22:51 +020056 if self.state == apdu_states.APDU_S_CLA and c == 0xff:
57 self.state = apdu_states.PTS
58 self.pts_buf = [c]
59 else:
60 self.buf.append(c)
61 self.state = apdu_states(self.state.value + 1)
Christina Quast79c2a3a2015-04-14 14:55:13 +020062
Christina Quaste64aa5b2015-04-14 15:07:33 +020063 def func_APDU_S_P3(self, c):
Christina Quast79c2a3a2015-04-14 14:55:13 +020064 self.buf.append(c)
Christina Quast51925a62015-04-14 21:04:14 +020065 self.data_remaining = 256 if c == 0 else c
Christina Quast59dae922015-05-14 16:58:37 +020066 self.state = apdu_states.APDU_S_SW1
Christina Quast79c2a3a2015-04-14 14:55:13 +020067
68 def func_APDU_S_DATA(self, c):
69 self.buf.append(c)
Christina Quast9547e9f2015-04-14 22:18:30 +020070 self.data.append(c)
Christina Quast79c2a3a2015-04-14 14:55:13 +020071 self.data_remaining -= 1
Christina Quast51925a62015-04-14 21:04:14 +020072 if self.data_remaining == 0:
Christina Quastfb91bb72015-04-18 13:31:42 +020073 self.state = apdu_states.APDU_S_SW1
Christina Quast79c2a3a2015-04-14 14:55:13 +020074
75 def func_APDU_S_DATA_SINGLE(self, c):
76 self.buf.append(c)
77 self.data_remaining -= 1
Christina Quastd4c8b512015-04-14 15:53:13 +020078 self.state = apdu_states.APDU_S_SW1
Christina Quast79c2a3a2015-04-14 14:55:13 +020079
80 def func_APDU_S_SW1(self, c):
Christina Quaste64aa5b2015-04-14 15:07:33 +020081 if (c == 0x60):
Christina Quast79c2a3a2015-04-14 14:55:13 +020082 print("APDU_S_SW1: NULL")
83 else:
84 # check for 'all remaining' type ACK
85 if c == self.ins or c == self.ins + 1 or c == ~(self.ins+1):
86 print("ACK")
Christina Quast9547e9f2015-04-14 22:18:30 +020087 self.data = []
Christina Quast59dae922015-05-14 16:58:37 +020088 if self.ins in self.INS_data_expected:
89 self.state = apdu_states.APDU_S_SEND_DATA
90 else:
91 self.state = apdu_states.APDU_S_DATA
Christina Quast79c2a3a2015-04-14 14:55:13 +020092 else:
93 # check for 'only next byte' type ACK */
Christina Quaste64aa5b2015-04-14 15:07:33 +020094 if c == ~(self.ins):
Christina Quastd4c8b512015-04-14 15:53:13 +020095 self.state = apdu_states.APDU_S_DATA_SINGLE
Christina Quast79c2a3a2015-04-14 14:55:13 +020096 else:
97 # must be SW1
Christina Quast9547e9f2015-04-14 22:18:30 +020098 self.sw1 = c
Christina Quast79c2a3a2015-04-14 14:55:13 +020099 self.buf.append(c)
Christina Quastd4c8b512015-04-14 15:53:13 +0200100 self.state = apdu_states.APDU_S_SW2
Christina Quast79c2a3a2015-04-14 14:55:13 +0200101
Christina Quaste64aa5b2015-04-14 15:07:33 +0200102 def func_APDU_S_SW2(self, c):
Christina Quast79c2a3a2015-04-14 14:55:13 +0200103 self.buf.append(c)
Christina Quast9547e9f2015-04-14 22:18:30 +0200104 self.sw2 = c
Christina Quastfb91bb72015-04-18 13:31:42 +0200105 print("APDU:", HEX(self.ins), HEX(self.buf))
Christina Quast9547e9f2015-04-14 22:18:30 +0200106 self.state = apdu_states.APDU_S_FIN
Christina Quaste64aa5b2015-04-14 15:07:33 +0200107
108 Apdu_S = {
Christina Quastd4c8b512015-04-14 15:53:13 +0200109 apdu_states.APDU_S_CLA : func_APDU_S_CLA_P1_P2,
110 apdu_states.APDU_S_INS : func_APDU_S_INS,
111 apdu_states.APDU_S_P1 : func_APDU_S_CLA_P1_P2,
112 apdu_states.APDU_S_P2 : func_APDU_S_CLA_P1_P2,
113 apdu_states.APDU_S_P3 : func_APDU_S_P3,
Christina Quastfb91bb72015-04-18 13:31:42 +0200114 apdu_states.APDU_S_SEND_DATA : func_APDU_S_DATA,
Christina Quastd4c8b512015-04-14 15:53:13 +0200115 apdu_states.APDU_S_DATA : func_APDU_S_DATA,
116 apdu_states.APDU_S_DATA_SINGLE : func_APDU_S_DATA_SINGLE,
117 apdu_states.APDU_S_SW1 : func_APDU_S_SW1,
Christina Quast0d98b9f2015-05-03 14:22:51 +0200118 apdu_states.APDU_S_SW2 : func_APDU_S_SW2,
119 apdu_states.PTS : func_PTS }
Christina Quastd4c8b512015-04-14 15:53:13 +0200120
Christina Quast19ed5292015-06-24 15:23:59 +0200121 INS_data_expected = [0xC0, 0xB0, 0xB2, 0x12, 0xF2]
Christina Quastfb91bb72015-04-18 13:31:42 +0200122
Christina Quastd4c8b512015-04-14 15:53:13 +0200123 def split(self, c):
Christina Quast19ed5292015-06-24 15:23:59 +0200124 # if c == 0xA0:
125 # self.state = apdu_states.APDU_S_CLA
126 print("state: ", self.state, hex(c))
Christina Quastd4c8b512015-04-14 15:53:13 +0200127 self.Apdu_S[self.state](self, c)
Christina Quaste64aa5b2015-04-14 15:07:33 +0200128
129
130if __name__ == '__main__':
Christina Quast51925a62015-04-14 21:04:14 +0200131 msg1 = [0xA0, 0xA4, 0x00, 0x00, 0x02, 0xA4, 0x7F, 0x20, 0x9F, 0x16]
132 msg2 = [0xA0, 0xC0, 0x00, 0x00, 0x16, 0xC0,
133 0x00, 0x00, 0x00, 0x00, 0x7F, 0x20,
134 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x09, 0x91, 0x00, 0x17, 0x04, 0x00, 0x00, 0x00,
136 0x83, 0x8A, 0x90, 0x00]
Christina Quast59dae922015-05-14 16:58:37 +0200137 msg3 = [0xa0, 0xc0, 0x00, 0x00, 0x16, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f,
138 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x91, 0x00, 0x17,
139 0x04, 0x00, 0x83, 0x8a, 0x83, 0x8a, 0x90]
140
Christina Quast0d98b9f2015-05-03 14:22:51 +0200141 pts = [0xff, 0x00, 0xff]
Christina Quast9547e9f2015-04-14 22:18:30 +0200142 apdus = []
143 apdu = Apdu_splitter()
Christina Quast59dae922015-05-14 16:58:37 +0200144 for c in pts + msg2 + msg1 + msg3:
Christina Quast9547e9f2015-04-14 22:18:30 +0200145 apdu.split(c)
146 if apdu.state == apdu_states.APDU_S_FIN:
147 apdus.append(apdu)
148 apdu = Apdu_splitter()
149 for a in apdus:
Christina Quastfb91bb72015-04-18 13:31:42 +0200150 print(HEX(a.buf))