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