annotate libcommon/apdu.c @ 45:9eb5460f51a6

main tools: support both pcsc and serial back ends
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 21 Mar 2021 01:56:49 +0000
parents c9ef9e91dd8e
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
9
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
1 #include <sys/types.h>
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
2 #include <ctype.h>
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
3 #include <stdio.h>
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
4 #include <stdlib.h>
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
5 #include <string.h>
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
6 #include <strings.h>
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
7
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
8 extern FILE *cpipeF, *rpipeF;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
9
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
10 u_char sim_resp_data[258];
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
11 unsigned sim_resp_data_len, sim_resp_sw;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
12
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
13 static void
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
14 send_cmd(cmd_apdu, cmd_apdu_len)
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
15 u_char *cmd_apdu;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
16 unsigned cmd_apdu_len;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
17 {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
18 unsigned n;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
19
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
20 for (n = 0; n < cmd_apdu_len; n++)
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
21 fprintf(cpipeF, "%02X", cmd_apdu[n]);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
22 putc('\n', cpipeF);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
23 fflush(cpipeF);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
24 }
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
25
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
26 static
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
27 parse_response_hex_string(input)
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
28 char *input;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
29 {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
30 char *cp;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
31
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
32 sim_resp_data_len = 0;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
33 for (cp = input; *cp; cp += 2) {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
34 if (!isxdigit(cp[0]) || !isxdigit(cp[1])) {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
35 fprintf(stderr,
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
36 "comm error: invalid hex string from back end\n");
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
37 return(-1);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
38 }
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
39 sim_resp_data[sim_resp_data_len++] =
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
40 (decode_hex_digit(cp[0]) << 4) |
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
41 decode_hex_digit(cp[1]);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
42 }
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
43 return(0);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
44 }
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
45
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
46 apdu_exchange(cmd_apdu, cmd_apdu_len)
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
47 u_char *cmd_apdu;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
48 unsigned cmd_apdu_len;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
49 {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
50 char inbuf[518], *cp;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
51 u_char *sw;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
52 int rc;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
53
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
54 send_cmd(cmd_apdu, cmd_apdu_len);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
55 if (!fgets(inbuf, sizeof inbuf, rpipeF)) {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
56 fprintf(stderr, "comm error: EOF reading from back end\n");
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
57 return(-1);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
58 }
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
59 cp = index(inbuf, '\n');
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
60 if (!cp) {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
61 fprintf(stderr,
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
62 "comm error: response from back end has no newline\n");
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
63 return(-1);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
64 }
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
65 *cp = '\0';
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
66 if (!inbuf[0]) {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
67 fprintf(stderr,
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
68 "comm error: response from back end is an empty line\n");
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
69 return(-1);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
70 }
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
71 if (!isxdigit(inbuf[0]) || !isxdigit(inbuf[1]) || !isxdigit(inbuf[2])
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
72 || !isxdigit(inbuf[3])) {
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
73 /* we got a back end error message */
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
74 fprintf(stderr, "%s\n", inbuf);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
75 return(-1);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
76 }
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
77 rc = parse_response_hex_string(inbuf);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
78 if (rc < 0)
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
79 return(rc);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
80 sim_resp_data_len -= 2;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
81 sw = sim_resp_data + sim_resp_data_len;
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
82 sim_resp_sw = (sw[0] << 8) | sw[1];
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
83 return(0);
c9ef9e91dd8e new libcommon, initial version
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
84 }