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