xref: /aosp_15_r20/external/libese/tools/ese_relay/ese_relay.c (revision 5c4dab75aa57366379dce576b1a9e082a44e2b3a)
1*5c4dab75SAndroid Build Coastguard Worker /*
2*5c4dab75SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*5c4dab75SAndroid Build Coastguard Worker  *
4*5c4dab75SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*5c4dab75SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*5c4dab75SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*5c4dab75SAndroid Build Coastguard Worker  *
8*5c4dab75SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*5c4dab75SAndroid Build Coastguard Worker  *
10*5c4dab75SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*5c4dab75SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*5c4dab75SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*5c4dab75SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*5c4dab75SAndroid Build Coastguard Worker  * limitations under the License.
15*5c4dab75SAndroid Build Coastguard Worker  *
16*5c4dab75SAndroid Build Coastguard Worker  * Hack-y server to forward communication with an eSE during development.
17*5c4dab75SAndroid Build Coastguard Worker  * See README.md for more information.
18*5c4dab75SAndroid Build Coastguard Worker  */
19*5c4dab75SAndroid Build Coastguard Worker 
20*5c4dab75SAndroid Build Coastguard Worker #include <arpa/inet.h>
21*5c4dab75SAndroid Build Coastguard Worker #include <linux/un.h>
22*5c4dab75SAndroid Build Coastguard Worker #include <stdint.h>
23*5c4dab75SAndroid Build Coastguard Worker #include <stdio.h>
24*5c4dab75SAndroid Build Coastguard Worker #include <string.h>
25*5c4dab75SAndroid Build Coastguard Worker #include <sys/socket.h>
26*5c4dab75SAndroid Build Coastguard Worker #include <unistd.h>
27*5c4dab75SAndroid Build Coastguard Worker 
28*5c4dab75SAndroid Build Coastguard Worker #define LOG_TAG "ese-relay"
29*5c4dab75SAndroid Build Coastguard Worker #include <ese/ese.h>
30*5c4dab75SAndroid Build Coastguard Worker #include <ese/log.h>
31*5c4dab75SAndroid Build Coastguard Worker 
32*5c4dab75SAndroid Build Coastguard Worker extern const uint8_t *kAtr;
33*5c4dab75SAndroid Build Coastguard Worker extern size_t kAtrLength;
34*5c4dab75SAndroid Build Coastguard Worker extern void *kEseOpenData;
35*5c4dab75SAndroid Build Coastguard Worker void ese_relay_init(struct EseInterface *ese);
36*5c4dab75SAndroid Build Coastguard Worker 
37*5c4dab75SAndroid Build Coastguard Worker /*
38*5c4dab75SAndroid Build Coastguard Worker  * Aligned with vpcd.h in
39*5c4dab75SAndroid Build Coastguard Worker  * https://frankmorgner.github.io/vsmartcard/virtualsmartcard
40*5c4dab75SAndroid Build Coastguard Worker  */
41*5c4dab75SAndroid Build Coastguard Worker #define CMD_POWER_OFF 0
42*5c4dab75SAndroid Build Coastguard Worker #define CMD_POWER_ON 1
43*5c4dab75SAndroid Build Coastguard Worker #define CMD_RESET 2
44*5c4dab75SAndroid Build Coastguard Worker #define CMD_ATR 4
45*5c4dab75SAndroid Build Coastguard Worker 
setup_socket(const char * name)46*5c4dab75SAndroid Build Coastguard Worker int setup_socket(const char *name) {
47*5c4dab75SAndroid Build Coastguard Worker   int fd;
48*5c4dab75SAndroid Build Coastguard Worker   struct sockaddr_un addr;
49*5c4dab75SAndroid Build Coastguard Worker 
50*5c4dab75SAndroid Build Coastguard Worker   memset(&addr, 0, sizeof(struct sockaddr_un));
51*5c4dab75SAndroid Build Coastguard Worker   addr.sun_family = AF_UNIX;
52*5c4dab75SAndroid Build Coastguard Worker   if (strlen(name) > UNIX_PATH_MAX - 1) {
53*5c4dab75SAndroid Build Coastguard Worker     ALOGE("Abstract listener name too long.");
54*5c4dab75SAndroid Build Coastguard Worker     return -1;
55*5c4dab75SAndroid Build Coastguard Worker   }
56*5c4dab75SAndroid Build Coastguard Worker   strncpy(&addr.sun_path[1], name, strlen(name));
57*5c4dab75SAndroid Build Coastguard Worker   fd = socket(AF_UNIX, SOCK_STREAM, 0);
58*5c4dab75SAndroid Build Coastguard Worker   if (fd == -1) {
59*5c4dab75SAndroid Build Coastguard Worker     ALOGE("Could not open socket.");
60*5c4dab75SAndroid Build Coastguard Worker     return fd;
61*5c4dab75SAndroid Build Coastguard Worker   }
62*5c4dab75SAndroid Build Coastguard Worker   if (bind(fd, (struct sockaddr *)&addr,
63*5c4dab75SAndroid Build Coastguard Worker            sizeof(sa_family_t) + strlen(name) + 1) == -1) {
64*5c4dab75SAndroid Build Coastguard Worker     ALOGE("Failed to bind to abstract socket name");
65*5c4dab75SAndroid Build Coastguard Worker     close(fd);
66*5c4dab75SAndroid Build Coastguard Worker     return -1;
67*5c4dab75SAndroid Build Coastguard Worker   }
68*5c4dab75SAndroid Build Coastguard Worker   return fd;
69*5c4dab75SAndroid Build Coastguard Worker }
70*5c4dab75SAndroid Build Coastguard Worker 
main()71*5c4dab75SAndroid Build Coastguard Worker int main() {
72*5c4dab75SAndroid Build Coastguard Worker   int server_fd = setup_socket(LOG_TAG);
73*5c4dab75SAndroid Build Coastguard Worker   struct EseInterface ese;
74*5c4dab75SAndroid Build Coastguard Worker   ese_relay_init(&ese);
75*5c4dab75SAndroid Build Coastguard Worker 
76*5c4dab75SAndroid Build Coastguard Worker   if (listen(server_fd, 4)) {
77*5c4dab75SAndroid Build Coastguard Worker     ALOGE("Failed to listen on socket.");
78*5c4dab75SAndroid Build Coastguard Worker     close(server_fd);
79*5c4dab75SAndroid Build Coastguard Worker     return -1;
80*5c4dab75SAndroid Build Coastguard Worker   }
81*5c4dab75SAndroid Build Coastguard Worker 
82*5c4dab75SAndroid Build Coastguard Worker   while (server_fd) {
83*5c4dab75SAndroid Build Coastguard Worker     struct sockaddr client_info;
84*5c4dab75SAndroid Build Coastguard Worker     socklen_t client_info_len = (socklen_t)sizeof(&client_info);
85*5c4dab75SAndroid Build Coastguard Worker     int client_fd;
86*5c4dab75SAndroid Build Coastguard Worker     uint32_t tx_len, data_read;
87*5c4dab75SAndroid Build Coastguard Worker     uint32_t rx_len;
88*5c4dab75SAndroid Build Coastguard Worker     uint16_t network_tx_len;
89*5c4dab75SAndroid Build Coastguard Worker     uint16_t network_rx_len;
90*5c4dab75SAndroid Build Coastguard Worker     uint8_t tx_buf[4096];
91*5c4dab75SAndroid Build Coastguard Worker     uint8_t rx_buf[4096];
92*5c4dab75SAndroid Build Coastguard Worker     int connected = 0;
93*5c4dab75SAndroid Build Coastguard Worker 
94*5c4dab75SAndroid Build Coastguard Worker     if ((client_fd = accept(server_fd, &client_info, &client_info_len)) == -1) {
95*5c4dab75SAndroid Build Coastguard Worker       ALOGE("Fatal error accept()ing a client connection.");
96*5c4dab75SAndroid Build Coastguard Worker       return -1;
97*5c4dab75SAndroid Build Coastguard Worker     }
98*5c4dab75SAndroid Build Coastguard Worker     printf("Client connected.\n");
99*5c4dab75SAndroid Build Coastguard Worker     connected = 1;
100*5c4dab75SAndroid Build Coastguard Worker     if (ese_open(&ese, kEseOpenData)) {
101*5c4dab75SAndroid Build Coastguard Worker       ALOGE("Cannot open hw");
102*5c4dab75SAndroid Build Coastguard Worker       if (ese_error(&ese))
103*5c4dab75SAndroid Build Coastguard Worker         ALOGE("eSE error (%d): %s", ese_error_code(&ese),
104*5c4dab75SAndroid Build Coastguard Worker               ese_error_message(&ese));
105*5c4dab75SAndroid Build Coastguard Worker       return 1;
106*5c4dab75SAndroid Build Coastguard Worker     }
107*5c4dab75SAndroid Build Coastguard Worker     printf("eSE is open\n");
108*5c4dab75SAndroid Build Coastguard Worker 
109*5c4dab75SAndroid Build Coastguard Worker     while (connected) {
110*5c4dab75SAndroid Build Coastguard Worker       printf("Listening for data from client\n");
111*5c4dab75SAndroid Build Coastguard Worker       if (read(client_fd, &network_tx_len, sizeof(network_tx_len)) !=
112*5c4dab75SAndroid Build Coastguard Worker           sizeof(network_tx_len)) {
113*5c4dab75SAndroid Build Coastguard Worker         ALOGE("Client disconnected.");
114*5c4dab75SAndroid Build Coastguard Worker         break;
115*5c4dab75SAndroid Build Coastguard Worker       }
116*5c4dab75SAndroid Build Coastguard Worker       tx_len = (uint32_t)ntohs(network_tx_len);
117*5c4dab75SAndroid Build Coastguard Worker       printf("tx_len: %u\n", tx_len);
118*5c4dab75SAndroid Build Coastguard Worker       if (tx_len == 0) {
119*5c4dab75SAndroid Build Coastguard Worker         ALOGE("Client had nothing to say. Goodbye.");
120*5c4dab75SAndroid Build Coastguard Worker         break;
121*5c4dab75SAndroid Build Coastguard Worker       }
122*5c4dab75SAndroid Build Coastguard Worker       if (tx_len > sizeof(tx_buf)) {
123*5c4dab75SAndroid Build Coastguard Worker         ALOGE("Client payload too large: %u", tx_len);
124*5c4dab75SAndroid Build Coastguard Worker         break;
125*5c4dab75SAndroid Build Coastguard Worker       }
126*5c4dab75SAndroid Build Coastguard Worker       for (data_read = 0; data_read < tx_len;) {
127*5c4dab75SAndroid Build Coastguard Worker         printf("Reading payload: %u of %u remaining\n", data_read, tx_len);
128*5c4dab75SAndroid Build Coastguard Worker         ssize_t bytes = read(client_fd, tx_buf + data_read, tx_len - data_read);
129*5c4dab75SAndroid Build Coastguard Worker         if (bytes < 0) {
130*5c4dab75SAndroid Build Coastguard Worker           ALOGE("Client abandoned hope during transmission.");
131*5c4dab75SAndroid Build Coastguard Worker           connected = 0;
132*5c4dab75SAndroid Build Coastguard Worker           break;
133*5c4dab75SAndroid Build Coastguard Worker         }
134*5c4dab75SAndroid Build Coastguard Worker         data_read += bytes;
135*5c4dab75SAndroid Build Coastguard Worker       }
136*5c4dab75SAndroid Build Coastguard Worker       /* Finally, we can transcieve. */
137*5c4dab75SAndroid Build Coastguard Worker       if (tx_len) {
138*5c4dab75SAndroid Build Coastguard Worker         uint32_t i;
139*5c4dab75SAndroid Build Coastguard Worker         printf("Sending %u bytes to card\n", tx_len);
140*5c4dab75SAndroid Build Coastguard Worker         printf("TX: ");
141*5c4dab75SAndroid Build Coastguard Worker         for (i = 0; i < tx_len; ++i)
142*5c4dab75SAndroid Build Coastguard Worker           printf("%.2X ", tx_buf[i]);
143*5c4dab75SAndroid Build Coastguard Worker         printf("\n");
144*5c4dab75SAndroid Build Coastguard Worker       }
145*5c4dab75SAndroid Build Coastguard Worker 
146*5c4dab75SAndroid Build Coastguard Worker       if (tx_len == 1) { /* Control request */
147*5c4dab75SAndroid Build Coastguard Worker         printf("Received a control request: %x\n", tx_buf[0]);
148*5c4dab75SAndroid Build Coastguard Worker         rx_len = 0;
149*5c4dab75SAndroid Build Coastguard Worker         switch (tx_buf[0]) {
150*5c4dab75SAndroid Build Coastguard Worker         case CMD_POWER_OFF:
151*5c4dab75SAndroid Build Coastguard Worker           ese.ops->hw_reset(&ese);
152*5c4dab75SAndroid Build Coastguard Worker           break;
153*5c4dab75SAndroid Build Coastguard Worker         case CMD_POWER_ON:
154*5c4dab75SAndroid Build Coastguard Worker           break;
155*5c4dab75SAndroid Build Coastguard Worker         case CMD_RESET:
156*5c4dab75SAndroid Build Coastguard Worker           ese.ops->hw_reset(&ese);
157*5c4dab75SAndroid Build Coastguard Worker           break;
158*5c4dab75SAndroid Build Coastguard Worker         case CMD_ATR:
159*5c4dab75SAndroid Build Coastguard Worker           /* Send a dummy ATR for another JCOP card */
160*5c4dab75SAndroid Build Coastguard Worker           rx_len = kAtrLength;
161*5c4dab75SAndroid Build Coastguard Worker           printf("Filling card RX buf with fake ATR (%u)\n", rx_len);
162*5c4dab75SAndroid Build Coastguard Worker           memcpy(rx_buf, kAtr, rx_len);
163*5c4dab75SAndroid Build Coastguard Worker           printf("Sending back ATR of length %u\n", rx_len);
164*5c4dab75SAndroid Build Coastguard Worker           break;
165*5c4dab75SAndroid Build Coastguard Worker         default:
166*5c4dab75SAndroid Build Coastguard Worker           ALOGE("Unknown control byte seen: %x", tx_buf[0]);
167*5c4dab75SAndroid Build Coastguard Worker         }
168*5c4dab75SAndroid Build Coastguard Worker         if (!rx_len)
169*5c4dab75SAndroid Build Coastguard Worker           continue;
170*5c4dab75SAndroid Build Coastguard Worker       } else {
171*5c4dab75SAndroid Build Coastguard Worker         rx_len = ese_transceive(&ese, tx_buf, tx_len, rx_buf, sizeof(rx_buf));
172*5c4dab75SAndroid Build Coastguard Worker         if (ese_error(&ese)) {
173*5c4dab75SAndroid Build Coastguard Worker           ALOGE("An error (%d) occurred: %s", ese_error_code(&ese),
174*5c4dab75SAndroid Build Coastguard Worker                 ese_error_message(&ese));
175*5c4dab75SAndroid Build Coastguard Worker           return -1;
176*5c4dab75SAndroid Build Coastguard Worker         }
177*5c4dab75SAndroid Build Coastguard Worker       }
178*5c4dab75SAndroid Build Coastguard Worker       if (rx_len > 0) {
179*5c4dab75SAndroid Build Coastguard Worker         uint32_t i;
180*5c4dab75SAndroid Build Coastguard Worker         printf("Read %d bytes from card\n", rx_len);
181*5c4dab75SAndroid Build Coastguard Worker         printf("RX: ");
182*5c4dab75SAndroid Build Coastguard Worker         for (i = 0; i < rx_len; ++i)
183*5c4dab75SAndroid Build Coastguard Worker           printf("%.2X ", rx_buf[i]);
184*5c4dab75SAndroid Build Coastguard Worker         printf("\n");
185*5c4dab75SAndroid Build Coastguard Worker       }
186*5c4dab75SAndroid Build Coastguard Worker 
187*5c4dab75SAndroid Build Coastguard Worker       /* Send to client */
188*5c4dab75SAndroid Build Coastguard Worker       network_rx_len = htons((uint16_t)rx_len);
189*5c4dab75SAndroid Build Coastguard Worker       if (write(client_fd, &network_rx_len, sizeof(network_rx_len)) !=
190*5c4dab75SAndroid Build Coastguard Worker           sizeof(network_rx_len)) {
191*5c4dab75SAndroid Build Coastguard Worker         ALOGE("Client abandoned hope during response size.");
192*5c4dab75SAndroid Build Coastguard Worker         break;
193*5c4dab75SAndroid Build Coastguard Worker       }
194*5c4dab75SAndroid Build Coastguard Worker 
195*5c4dab75SAndroid Build Coastguard Worker       for (data_read = 0; data_read < rx_len;) {
196*5c4dab75SAndroid Build Coastguard Worker         ssize_t bytes =
197*5c4dab75SAndroid Build Coastguard Worker             write(client_fd, rx_buf + data_read, rx_len - data_read);
198*5c4dab75SAndroid Build Coastguard Worker         if (bytes < 0) {
199*5c4dab75SAndroid Build Coastguard Worker           ALOGE("Client abandoned hope during response.");
200*5c4dab75SAndroid Build Coastguard Worker           connected = 0;
201*5c4dab75SAndroid Build Coastguard Worker           break;
202*5c4dab75SAndroid Build Coastguard Worker         }
203*5c4dab75SAndroid Build Coastguard Worker         data_read += bytes;
204*5c4dab75SAndroid Build Coastguard Worker       }
205*5c4dab75SAndroid Build Coastguard Worker       usleep(1000);
206*5c4dab75SAndroid Build Coastguard Worker     }
207*5c4dab75SAndroid Build Coastguard Worker     close(client_fd);
208*5c4dab75SAndroid Build Coastguard Worker     printf("Session ended\n\n");
209*5c4dab75SAndroid Build Coastguard Worker     ese_close(&ese);
210*5c4dab75SAndroid Build Coastguard Worker   }
211*5c4dab75SAndroid Build Coastguard Worker   return 0;
212*5c4dab75SAndroid Build Coastguard Worker }
213