FreeCalypso > hg > fc-sim-tools
comparison serial/exchange.c @ 43:be27d1c85861
serial: main function implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 20 Mar 2021 21:49:59 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
42:6cc3eea720cb | 43:be27d1c85861 |
---|---|
1 /* | |
2 * This module implements the main function of our back end: | |
3 * exchanging APDUs with the SIM. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <stdio.h> | |
8 | |
9 static | |
10 collect_one_byte() | |
11 { | |
12 u_char buf; | |
13 int rc; | |
14 | |
15 rc = collect_bytes_from_sim(&buf, 1); | |
16 if (rc < 0) | |
17 return rc; | |
18 else | |
19 return buf; | |
20 } | |
21 | |
22 static void | |
23 finish_sw(sw1, data, datalen) | |
24 unsigned sw1, datalen; | |
25 u_char *data; | |
26 { | |
27 unsigned sw2, n; | |
28 int rc; | |
29 | |
30 rc = collect_one_byte(); | |
31 if (rc < 0) { | |
32 printf("back end error at SW2 Rx step\n"); | |
33 return; | |
34 } | |
35 sw2 = rc; | |
36 for (n = 0; n < datalen; n++) | |
37 printf("%02X", data[n]); | |
38 printf("%02X%02X\n", sw1, sw2); | |
39 } | |
40 | |
41 static void | |
42 exchange_data_out(ins, data, datalen) | |
43 unsigned ins, datalen; | |
44 u_char *data; | |
45 { | |
46 int rc; | |
47 unsigned null_count, bytes_sent, ack, ack1; | |
48 | |
49 ack = ins & 0xFE; | |
50 ack1 = ~ins & 0xFE; | |
51 bytes_sent = 0; | |
52 null_count = 0; | |
53 for (;;) { | |
54 rc = collect_one_byte(); | |
55 if (rc < 0) { | |
56 printf("back end error at procedure byte step\n"); | |
57 return; | |
58 } | |
59 if (rc == 0x60) { | |
60 null_count++; | |
61 if (null_count >= 32) { | |
62 printf( | |
63 "ERROR: too many stalling NULL bytes received from SIM\n"); | |
64 return; | |
65 } | |
66 continue; | |
67 } | |
68 if ((rc & 0xF0) == 0x60 || (rc & 0xF0) == 0x90) { | |
69 finish_sw(rc, 0, 0); | |
70 return; | |
71 } | |
72 if ((rc & 0xFE) == ack) { | |
73 if (bytes_sent >= datalen) { | |
74 bad_xfer_req: printf( | |
75 "ERROR: SIM requests more xfer after we sent everything\n"); | |
76 return; | |
77 } | |
78 rc = send_bytes_to_sim(data + bytes_sent, | |
79 datalen - bytes_sent); | |
80 if (rc < 0) { | |
81 printf("back end error at data output step\n"); | |
82 return; | |
83 } | |
84 bytes_sent = datalen; | |
85 continue; | |
86 } | |
87 if ((rc & 0xFE) == ack1) { | |
88 if (bytes_sent >= datalen) | |
89 goto bad_xfer_req; | |
90 rc = send_bytes_to_sim(data + bytes_sent, 1); | |
91 if (rc < 0) { | |
92 printf("back end error at data output step\n"); | |
93 return; | |
94 } | |
95 bytes_sent++; | |
96 continue; | |
97 } | |
98 printf("ERROR: non-understood procedure byte %02X\n", rc); | |
99 return; | |
100 } | |
101 } | |
102 | |
103 static void | |
104 exchange_data_in(ins, datalen) | |
105 unsigned ins, datalen; | |
106 { | |
107 int rc; | |
108 unsigned null_count, bytes_rcvd, ack, ack1; | |
109 u_char data[256]; | |
110 | |
111 if (!datalen) | |
112 datalen = 256; | |
113 ack = ins & 0xFE; | |
114 ack1 = ~ins & 0xFE; | |
115 bytes_rcvd = 0; | |
116 null_count = 0; | |
117 for (;;) { | |
118 rc = collect_one_byte(); | |
119 if (rc < 0) { | |
120 printf("back end error at procedure byte step\n"); | |
121 return; | |
122 } | |
123 if (rc == 0x60) { | |
124 null_count++; | |
125 if (null_count >= 32) { | |
126 printf( | |
127 "ERROR: too many stalling NULL bytes received from SIM\n"); | |
128 return; | |
129 } | |
130 continue; | |
131 } | |
132 if ((rc & 0xF0) == 0x60 || (rc & 0xF0) == 0x90) { | |
133 finish_sw(rc, data, bytes_rcvd); | |
134 return; | |
135 } | |
136 if ((rc & 0xFE) == ack) { | |
137 if (bytes_rcvd >= datalen) { | |
138 bad_xfer_req: printf( | |
139 "ERROR: SIM requests more xfer after we received all expected data\n"); | |
140 return; | |
141 } | |
142 rc = collect_bytes_from_sim(data + bytes_rcvd, | |
143 datalen - bytes_rcvd); | |
144 if (rc < 0) { | |
145 printf("back end error at data input step\n"); | |
146 return; | |
147 } | |
148 bytes_rcvd = datalen; | |
149 continue; | |
150 } | |
151 if ((rc & 0xFE) == ack1) { | |
152 if (bytes_rcvd >= datalen) | |
153 goto bad_xfer_req; | |
154 rc = collect_one_byte(); | |
155 if (rc < 0) { | |
156 printf("back end error at data input step\n"); | |
157 return; | |
158 } | |
159 data[bytes_rcvd++] = rc; | |
160 continue; | |
161 } | |
162 printf("ERROR: non-understood procedure byte %02X\n", rc); | |
163 return; | |
164 } | |
165 } | |
166 | |
167 void | |
168 apdu_exchange(cmd_apdu, cmd_apdu_len) | |
169 u_char *cmd_apdu; | |
170 unsigned cmd_apdu_len; | |
171 { | |
172 int rc; | |
173 | |
174 rc = send_bytes_to_sim(cmd_apdu, 5); | |
175 if (rc < 0) { | |
176 printf("back end error at the command sending step\n"); | |
177 return; | |
178 } | |
179 if (cmd_apdu_len > 5) | |
180 exchange_data_out(cmd_apdu[1], cmd_apdu + 5, cmd_apdu_len - 5); | |
181 else | |
182 exchange_data_in(cmd_apdu[1], cmd_apdu[4]); | |
183 } |