Home | History | Annotate | Download | only in ese_replay
      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  * Usage:
     17  *   $0 [impl name] < line-by-line-input-and-expect
     18  */
     19 
     20 #include <ctype.h>
     21 #include <stdint.h>
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #include <unistd.h>
     26 
     27 #define LOG_TAG "ese-replay"
     28 #include <ese/ese.h>
     29 #include <ese/log.h>
     30 
     31 #include "buffer.h"
     32 #include "hw.h"
     33 #include "payload.h"
     34 
     35 const struct SupportedHardware kSupportedHardware = {
     36     .len = 3,
     37     .hw =
     38         {
     39             {
     40                 .name = "nq-nci",
     41                 .sym = "ESE_HW_NXP_PN80T_NQ_NCI_ops",
     42                 .lib = "libese-hw-nxp-pn80t-nq-nci.so",
     43                 .options = NULL,
     44             },
     45             {
     46                 .name = "fake",
     47                 .sym = "ESE_HW_FAKE_ops",
     48                 .lib = "libese-hw-fake.so",
     49                 .options = NULL,
     50             },
     51             {
     52                 .name = "echo",
     53                 .sym = "ESE_HW_ECHO_ops",
     54                 .lib = "libese-hw-echo.so",
     55                 .options = NULL,
     56             },
     57         },
     58 };
     59 
     60 int main(int argc, char **argv) {
     61   if (argc != 2) {
     62     printf("Usage:\n%s [hw_impl] < file_with_apdus\n\n"
     63            "File format:\n"
     64            "  hex-apdu-to-send hex-trailing-response-bytes\\n\n"
     65            "\n"
     66            "For example,\n"
     67            "  echo -e '00A4040000 9000\\n80CA9F7F00 9000\\n' | %s nq-nci\n",
     68            argv[0], argv[0]);
     69     print_supported_hardware(&kSupportedHardware);
     70     return 1;
     71   }
     72   int hw_id = find_supported_hardware(&kSupportedHardware, argv[1]);
     73   if (hw_id < 0) {
     74     fprintf(stderr, "Unknown hardware name: %s\n", argv[1]);
     75     return 3;
     76   }
     77   const struct Hardware *hw = &kSupportedHardware.hw[hw_id];
     78 
     79   struct EseInterface ese;
     80   printf("[-] Initializing eSE\n");
     81 
     82   if (!initialize_hardware(&ese, hw)) {
     83     fprintf(stderr, "Could not initialize hardware\n");
     84     return 2;
     85   }
     86   printf("eSE implementation selected: %s\n", ese_name(&ese));
     87   if (ese_open(&ese, hw->options)) {
     88     ALOGE("Cannot open hw");
     89     if (ese_error(&ese)) {
     90       ALOGE("eSE error (%d): %s", ese_error_code(&ese),
     91             ese_error_message(&ese));
     92     }
     93     return 5;
     94   }
     95   printf("eSE is open\n");
     96   struct Payload payload;
     97   if (!payload_init(&payload, 10 * 1024 * 1024, 1024 * 4)) {
     98     ALOGE("Failed to initialize payload.");
     99     return -1;
    100   }
    101 
    102   struct Buffer reply;
    103   buffer_init(&reply, 2048);
    104   while (!feof(stdin) && payload_read(&payload, stdin)) {
    105     payload_dump(&payload, stdout);
    106     reply.len = (uint32_t)ese_transceive(
    107         &ese, payload.tx.buffer, payload.tx.len, reply.buffer, reply.size);
    108     if ((int)reply.len < 0 || ese_error(&ese)) {
    109       printf("Transceive error. See logcat -s ese-replay\n");
    110       ALOGE("transceived returned failure: %d\n", (int)reply.len);
    111       if (ese_error(&ese)) {
    112         ALOGE("An error (%d) occurred: %s", ese_error_code(&ese),
    113               ese_error_message(&ese));
    114       }
    115       break;
    116     }
    117     buffer_dump(&reply, "", "Response", 240, stdout);
    118     if (reply.len < payload.expected.len) {
    119       printf("Received less data than expected: %u < %u\n", reply.len,
    120              payload.expected.len);
    121       break;
    122     }
    123 
    124     /* Only compare the end. This allows a simple APDU success match. */
    125     if (memcmp(payload.expected.buffer,
    126                (reply.buffer + reply.len) - payload.expected.len,
    127                payload.expected.len)) {
    128       printf("Response did not match. Aborting!\n");
    129       break;
    130     }
    131   }
    132   buffer_free(&reply);
    133   printf("Transmissions complete.\n");
    134   ese_close(&ese);
    135   release_hardware(hw);
    136   return 0;
    137 }
    138