1 /* 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 32 extern const uint8_t *kAtr; 33 extern size_t kAtrLength; 34 extern void *kEseOpenData; 35 void 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 46 int 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 71 int main() { 72 int server_fd = setup_socket(LOG_TAG); 73 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 } 213