FreeCalypso > hg > freecalypso-tools
comparison target-utils/simagent/exchange.c @ 783:c136a1a2474b
simagent: initial implementation of APDU exchange
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 13 Mar 2021 22:06:08 +0000 |
parents | |
children | 839bf41e7be0 |
comparison
equal
deleted
inserted
replaced
782:badc5399d641 | 783:c136a1a2474b |
---|---|
1 /* | |
2 * This module implements our main function: exchange of command | |
3 * and response APDUs. | |
4 */ | |
5 | |
6 #include "types.h" | |
7 | |
8 extern int sim_if_state; | |
9 | |
10 static void | |
11 finish_sw(sw1, data, datalen) | |
12 unsigned sw1, datalen; | |
13 u8 *data; | |
14 { | |
15 unsigned sw2, n; | |
16 int rc; | |
17 | |
18 rc = rx_sim_byte_hl(); | |
19 if (rc < 0) | |
20 return; | |
21 sw2 = rc; | |
22 for (n = 0; n < datalen; n++) | |
23 printf("%02X", data[n]); | |
24 printf("%02X%02X\n", sw1, sw2); | |
25 } | |
26 | |
27 static void | |
28 exchange_data_out(ins, data, datalen) | |
29 unsigned ins, datalen; | |
30 u8 *data; | |
31 { | |
32 int rc; | |
33 unsigned null_count, bytes_sent, ack, ack1; | |
34 | |
35 ack = ins & 0xFE; | |
36 ack1 = ~ins & 0xFE; | |
37 bytes_sent = 0; | |
38 null_count = 0; | |
39 for (;;) { | |
40 rc = rx_sim_byte_hl(); | |
41 if (rc < 0) | |
42 return; | |
43 if (rc == 0x60) { | |
44 null_count++; | |
45 if (null_count >= 32) { | |
46 printf( | |
47 "ERROR: too many stalling NULL bytes received from SIM\n"); | |
48 return; | |
49 } | |
50 continue; | |
51 } | |
52 if ((rc & 0xF0) == 0x60 || (rc & 0xF0) == 0x90) { | |
53 finish_sw(rc, 0, 0); | |
54 return; | |
55 } | |
56 if ((rc & 0xFE) == ack) { | |
57 if (bytes_sent >= datalen) { | |
58 bad_xfer_req: printf( | |
59 "ERROR: SIM requests more xfer after we sent everything\n"); | |
60 return; | |
61 } | |
62 rc = send_to_sim(data + bytes_sent, | |
63 datalen - bytes_sent); | |
64 if (rc < 0) | |
65 return; | |
66 bytes_sent = datalen; | |
67 continue; | |
68 } | |
69 if ((rc & 0xFE) == ack1) { | |
70 if (bytes_sent >= datalen) | |
71 goto bad_xfer_req; | |
72 rc = send_to_sim(data + bytes_sent, 1); | |
73 if (rc < 0) | |
74 return; | |
75 bytes_sent++; | |
76 continue; | |
77 } | |
78 printf("ERROR: non-understood procedure byte %02X\n", rc); | |
79 return; | |
80 } | |
81 } | |
82 | |
83 static void | |
84 exchange_data_in(ins, datalen) | |
85 unsigned ins, datalen; | |
86 { | |
87 printf("ERROR: data in mode not implemented yet\n"); | |
88 } | |
89 | |
90 void | |
91 cmd_exchange(argstr) | |
92 char *argstr; | |
93 { | |
94 u8 cmd[260]; | |
95 int rc; | |
96 | |
97 if (sim_if_state != 2) { | |
98 printf("ERROR: SIM interface is not up\n"); | |
99 return; | |
100 } | |
101 rc = decode_hex_string_arg(argstr, cmd, 260); | |
102 if (rc < 0) | |
103 return; | |
104 if (rc < 5) { | |
105 printf("ERROR: command APDU is shorter than 5 bytes\n"); | |
106 return; | |
107 } | |
108 rc = flush_rx_fifo(); | |
109 if (rc < 0) | |
110 return; | |
111 rc = send_to_sim(cmd, 5); | |
112 if (rc < 0) | |
113 return; | |
114 if (rc > 5) | |
115 exchange_data_out(cmd[1], cmd + 5, rc - 5); | |
116 else | |
117 exchange_data_in(cmd[1], cmd[4]); | |
118 } |