BOOL ReaderLeds(const char *szReaderName, BYTE red, BYTE green, BYTE blue)
{
  BYTE c_apdu[256];
  DWORD c_apdu_len;
  BYTE r_apdu[256];
  DWORD r_apdu_len;

  CARD_CHANNEL_T Channel = { 0 };
  BOOL rc = FALSE;  

  Channel.bSilent = TRUE;
  
  /* Try to connect to the card in the reader (if there's one) */
  if (CardConnect(szReaderName, &Channel))
  {
    /* Card connected, use the APDU method */   
    c_apdu_len = 0;
    c_apdu[c_apdu_len++] = 0xFF;
    c_apdu[c_apdu_len++] = 0xF0;
    c_apdu[c_apdu_len++] = 0x00;
    c_apdu[c_apdu_len++] = 0x00;
    c_apdu[c_apdu_len++] = 4;
    c_apdu[c_apdu_len++] = 0x1E;
    c_apdu[c_apdu_len++] = red;
    c_apdu[c_apdu_len++] = green;
    c_apdu[c_apdu_len++] = blue;
 
    r_apdu_len = sizeof(r_apdu);
    rc = CardTransmit(&Channel, c_apdu, c_apdu_len, r_apdu, &r_apdu_len);

    CardDisconnect(&Channel, SCARD_LEAVE_CARD);
  }
  
  if (!rc)
  {
    /* No card in the reader (or any other error...) try a direct connection to the reader itself */
    if (ReaderConnect(szReaderName, &Channel))
    {
      c_apdu_len = 0;
      c_apdu[c_apdu_len++] = 0x58;
      c_apdu[c_apdu_len++] = 0x1E;
      c_apdu[c_apdu_len++] = red;
      c_apdu[c_apdu_len++] = green;
      c_apdu[c_apdu_len++] = blue;

      r_apdu_len = sizeof(r_apdu);
      rc = ReaderControl(&Channel, c_apdu, c_apdu_len, r_apdu, &r_apdu_len);

      CardDisconnect(&Channel, SCARD_LEAVE_CARD);
    }
  }

  return rc;
}
int
main(int argc, const char *argv[])
{
  nfc_device *pnd;
  nfc_target nt;
  nfc_context *context;
  nfc_init(&context);
  
  printf("\nRunning checks...\n");

  if (context == NULL) {
    printf("Unable to init libnfc (malloc)\n");
    exit(EXIT_FAILURE);
  } 

  const char *acLibnfcVersion = nfc_version();
  (void)argc;
  printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);

  pnd = nfc_open(context, NULL);

  if (pnd == NULL) {
    printf("ERROR: %s", "Unable to open NFC device.");
    exit(EXIT_FAILURE);
  }
  if (nfc_initiator_init(pnd) < 0) {
    nfc_perror(pnd, "nfc_initiator_init");
    exit(EXIT_FAILURE);
  }

  printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));

  const nfc_modulation nmMifare = {
    .nmt = NMT_ISO14443A,
    .nbr = NBR_106,
  };
  // nfc_set_property_bool(pnd, NP_AUTO_ISO14443_4, true);
  printf("Polling for target...\n");
  while (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0);
  printf("Target detected! Running command set...\n\n");
  uint8_t capdu[264];
  size_t capdulen;
  uint8_t rapdu[264];
  size_t rapdulen;
  // Select application
  memcpy(capdu, "\x00\xA4\x04\x00\x07\xF0\x39\x41\x48\x14\x81\x00\x00", 13);
  capdulen=13;
  rapdulen=sizeof(rapdu);

  printf("Sending ADPU SELECT...\n");
  if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
    exit(EXIT_FAILURE);
  }
  if (rapdulen < 2 || rapdu[rapdulen-2] != 0x90 || rapdu[rapdulen-1] != 0x00) {
    exit(EXIT_FAILURE);
  }
  printf("Application selected!\n\n");

  // Select Capability Container
  memcpy(capdu, "\x00\xa4\x00\x0c\x02\xe1\x03", 7);  
  capdulen=7;
  rapdulen=sizeof(rapdu);
  
  printf("Sending CC SELECT...\n");
  if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0)
    exit(EXIT_FAILURE);
  if (rapdulen < 2 || rapdu[rapdulen-2] != 0x90 || rapdu[rapdulen-1] != 0x00) {
    capdu[3]='\x00'; // Maybe an older Tag4 ?
    if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0)
      exit(EXIT_FAILURE);
  }
  printf("Capability Container selected!\n\n");

  // Read Capability Container
  memcpy(capdu, "\x00\xb0\x00\x00\x0f", 5);  
  capdulen=5;
  rapdulen=sizeof(rapdu);
  
  printf("Sending ReadBinary from CC...\n");
  if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0)
    exit(EXIT_FAILURE);
  if (rapdulen < 2 || rapdu[rapdulen-2] != 0x90 || rapdu[rapdulen-1] != 0x00)
    exit(EXIT_FAILURE);
  printf("\nCapability Container header:\n");
  size_t  szPos;
  for (szPos = 0; szPos < rapdulen-2; szPos++) {
    printf("%02x ", rapdu[szPos]);
  }
  printf("\n\n");

  // NDEF Select
  memcpy(capdu, "\x00\xa4\x00\x0C\x02\xE1\x04", 7);
  capdulen=7;
  rapdulen=sizeof(rapdu);
  printf("Sending NDEF Select...\n");
  if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0)
    exit(EXIT_FAILURE);
  if (rapdulen < 2 || rapdu[rapdulen-2] != 0x90 || rapdu[rapdulen-1] != 0x00)
    exit(EXIT_FAILURE);
  printf("\n");

  // ReadBinary
  memcpy(capdu, "\x00\xb0\x00\x00\x02", 5);
  capdulen=5;
  rapdulen=sizeof(rapdu);
  printf("Sending ReadBinary NLEN...\n");
  if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0)
    exit(EXIT_FAILURE);
  if (rapdulen < 2 || rapdu[rapdulen-2] != 0x90 || rapdu[rapdulen-1] != 0x00)
    exit(EXIT_FAILURE);
  printf("\n");

  // ReadBinary - Get NDEF data
  memcpy(capdu, "\x00\xb0\x00\x00\x0f", 5);
  capdulen=5;
  rapdulen=sizeof(rapdu);
  printf("Sending ReadBinary, get NDEF data...\n");
  if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0)
    exit(EXIT_FAILURE);
  if (rapdulen < 2 || rapdu[rapdulen-2] != 0x90 || rapdu[rapdulen-1] != 0x00)
    exit(EXIT_FAILURE);
  printf("\n");

  printf("Wrapping up, closing session.\n\n");

  nfc_close(pnd);
  nfc_exit(context);
  exit(EXIT_SUCCESS);
}
Example #3
0
void nfcProtocol() {
    char message[1024];
    char UAFMessage[2048];
    memoryStruct chunk;

    uint8_t capdu[264];
    size_t capdulen;
    uint8_t rapdu[264];
    size_t rapdulen;
    char *response = 0;


    const nfc_modulation nmMifare = {
        .nmt = NMT_ISO14443A,
        .nbr = NBR_106,
    };

    printf("Polling for target...\n");
    while (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0);
    printf("Target detected!\n");


    // Select application
    memcpy(capdu, APDU, sizeof (APDU));
    capdulen = sizeof (APDU); // 13
    rapdulen = sizeof (rapdu);
    if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0)
        exit(EXIT_FAILURE);
    printf("Application selected!\n");

    if (strncmp(rapdu, DOOR_HELLO, (int) rapdulen)) {
        printf("** Opss ** I'm expecting HELLO msg, but card sent to me: %s. len: %d\n", response, (int) rapdulen);
        return;
    }

    // FIDO Auth Request Message
    printf("Doing AuthRequest to FIDO UAF Server\n");
    sprintf(UAFMessage, AUTH_REQUEST_MSG, SCHEME, HOSTNAME, PORT, AUTH_REQUEST_ENDPOINT);
    chunk = getHttpRequest(UAFMessage);

    if (chunk.size <= 0) {
        printf("** Opss ** Error to connect to FIDO Server\n");
        memcpy(capdu, "ERROR", 5);
        capdulen = 5;
        rapdulen = sizeof (rapdu);
        if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
            printf("Error to sent error message to card...\n");
        }
        return;
    }

    size_t blocks = (chunk.size / BLOCK_SIZE) + 1;

    char *buffer[blocks];
    blockSplit(chunk.memory, buffer, blocks);
    sprintf(message, "BLOCK:%ld", blocks);
    printf("Sending number of blocks: %s\n", message);
    free(chunk.memory);

    memcpy(capdu, message, strlen(message));
    capdulen = strlen(message);
    rapdulen = sizeof (rapdu);
    if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
        printf("Error to send number of blocks\n");
        return;
    }

    int totalSent = 0;

    if (strncmp(rapdu, DOOR_NEXT, (int) rapdulen)) {
        printf("** Opss ** I'm expecting NEXT msg, but card sent to me: %s. len: %d", response, (int) rapdulen);
        return;
    }

    response = NULL;
    do { // Sending UAFRequestMessage to card
        memcpy(capdu, buffer[totalSent], strlen(buffer[totalSent]));
        capdulen = strlen(buffer[totalSent]);
        rapdulen = sizeof (rapdu);
        if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
            int i = strlen(buffer[totalSent]);
            printf("error to send UAFRequestMessage to card. Message size: %d, message: %s\n", i, buffer[totalSent]);
            return;
        }

        if (strncmp(rapdu, DOOR_OK, (int) rapdulen)) {
            printf("** Opss ** I'm expecting OK msg, but card sent to me: %s. len: %d", response, (int) rapdulen);
            return;
        }
        response = NULL;
        free(buffer[totalSent]);
        totalSent++;
    } while (totalSent < blocks);


    printf("Sending READY!\n");
    memcpy(capdu, DOOR_READY, sizeof (DOOR_READY));
    capdulen = strlen(DOOR_READY);
    rapdulen = sizeof (rapdu);
    unsigned long timeout = LONG_MAX;
    do {
        if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
            printf("Error to received WAIT\n");
            return;
        }

        if (strncmp(rapdu, DOOR_WAIT, (int) rapdulen) == 0) {
            continue;
        }

        if (strncmp(rapdu, DOOR_DONE, (int) rapdulen) == 0) {
            printf("Sending RESPONSE!\n");
            memcpy(capdu, DOOR_RESPONSE, sizeof (DOOR_RESPONSE));
            capdulen = strlen(DOOR_RESPONSE);
            rapdulen = sizeof (rapdu);
            if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
                printf("Error RESPONSE...\n");
                return;
            }
            break;
        }
        timeout--;
    } while (timeout > 0);

    if (timeout == 0) {
        printf("Error. Client is not responding...\n");
        return;
    }

    strncpy(message, rapdu, (int) rapdulen);
    char *p = strtok(message, ":");
    char *endptr;
    long val;
    if (strcmp(p, "BLOCK") == 0) {
        p = strtok(NULL, ":");
        val = strtol(p, &endptr, 10);
        char *UAFmsg = malloc(sizeof (char) * BLOCK_SIZE * val + 1);
        UAFmsg[0] = '\0';
        do {
            printf("Sending NEXT!\n");
            memcpy(capdu, DOOR_NEXT, sizeof (DOOR_NEXT));
            capdulen = strlen(DOOR_NEXT);
            rapdulen = sizeof (rapdu);
            if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
                printf("Error NEXT\n");
                return;
            }
            strncat(UAFmsg, rapdu, (int) rapdulen);
            val--;
        } while (val > 0);
        // FIDO Auth Request Message
        printf("Forwarding card response to FIDO UAF Server: \n");
        sprintf(UAFMessage, AUTH_REQUEST_MSG, SCHEME, HOSTNAME, PORT, AUTH_RESPONSE_ENDPOINT);
        //curlFetchStruct *result = postHttpRequest(UAFMessage, UAFmsg);
        json_object *result = postHttpRequest(UAFMessage, UAFmsg);
        free(UAFmsg);

        //        if (result->size <= 0) {
        if (result == NULL) {
            printf("Error to connect to FIDO Server\n");
            memcpy(capdu, "ERROR", 5);
            capdulen = 5;
            rapdulen = sizeof (rapdu);
            if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
                printf("Error to send response to card\n");
            }
            return;
        }
        printf("Resul payload: %s \n", json_object_to_json_string(result));
        const char *resultStr = json_object_to_json_string(result);

        
        if (strstr(resultStr, "SUCCESS") == NULL) {
            printf("Access denied!\n");
            memcpy(capdu, DOOR_DENY, sizeof (DOOR_DENY));
            capdulen = strlen(DOOR_DENY);
            rapdulen = sizeof (rapdu);
            if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
                return;
            }
        } else {
            printf("Access granted!\n");
            memcpy(capdu, DOOR_GRANTED, sizeof (DOOR_GRANTED));
            capdulen = strlen(DOOR_GRANTED);
            rapdulen = sizeof (rapdu);
            if (CardTransmit(pnd, capdu, capdulen, rapdu, &rapdulen) < 0) {
                return;
            }
            doorlock(1);
            doorlock(0);
        }
        /* free json object */
        json_object_put(result);
        
        strncpy(message, rapdu, (int) rapdulen);
        if (strstr(message, "BYE") != NULL) {
            printf("bye!\n");
        } else {
            printf(":-(\n");
        }
    }
}