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 }