Home | History | Annotate | Download | only in ese_relay
      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