ChameleonMini icon indicating copy to clipboard operation
ChameleonMini copied to clipboard

Request for input about scriptable uses for the Chameleon Mini

Open maxieds opened this issue 3 years ago • 1 comments

I realize that this is slightly off topic, but it is still well within the interest level of this issues board. I would like to know more about how different users are working with the Chameleon Mini devices so that I can try to prepare for a new feature in my CMLD Android logger app.

After working (slogging, really) through writing duplicate code to test that my recent DESFire pull request is functional (see sources here), I finally decided to start on adding a small (mini) shell scripting like language to my application using an ANTLR4 grammar. The idea is to be able to run reusable batch scripts on the go that are much easier to write out and modify than the C counterparts in libnfc.

Does anyone have other good suggestions of uses for this, or must includes for script capabilities? I would appreciate any contributions (pull requests?) to a working library of example scripts I'm putting together. The core syntax is functionally below and the main functions so far are described here (in ANTLR4 syntax).

My motivating example is to re-write a portable version of the nfc-anticol utility. My schematic for how this works (will be working soon :)) is shown below:

/**
 * @file nfc-anticol.c
 * @brief Generates one ISO14443-A anti-collision process -- by-hand --
 */

/*
 * nfc-anticol.sh
 *
 * A demo of the Chameleon Mini Live Debugger mini terminal scripting
 * language to show key features and syntax that it can accomplish in this
 * application. The idea is that this platform makes it quick and simple to
 * automate running reusable batches of Chameleon terminal commands
 * on the go with the Droid device.
 *
 * https://github.com/maxieds/ChameleonMiniLiveDebugger
 *
 * Author: Maxie D. Schmidt (@maxieds)
 * Created: 2020.10.26
 */

$SAK_FLAG_ATS_SUPPORTED=0x20
$CASCADE_BIT=0x04

// Note that the array initializer list syntax only
// works with byte type literals:
$abtReqa = { 0x26 }
$abtSelectAll = { 0x93, 0x20 }
$abtSelectTag = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
$abtRats = { 0xe0, 0x50, 0x00, 0x00 }
$abtHalt = { 0x50, 0x00, 0x00, 0x00 }

// Always start with Cascade Level 1 (CL1)
$szCL = 1
$szAts = 0

// Send the 7 bits request command specified in ISO 14443A (0x26)
$abtRx = $$(Sprintf("SEND %s", AsHexString($abtReqa)))
if($abtRx->isError) {
     Printf("Error: No tag available\n");
     Exit(-1);
}
$abtAtqa = GetSubarray($abtRx, 0, 2)

// Anti-collision
$abtRx = $$(Sprintf("SEND %s", AsHexString($abtSelectAll)))

// Check answer
if (($abtRx[0] ^ $abtRx[1] ^ $abtRx[2] ^ $abtRx[3] ^ $abtRx[4]) != 0) {
     Printf("WARNING: BCC check failed!\n");
}

// Save the UID CL1
// memcpy(abtRawUid, abtRx, 4);
$abtRawUid = GetSubarray($abtRx, 0, 4)

// Prepare and send CL1 Select-Command
$abtSelectTag[2:] = $abtRx[0:5]
$abtSelectTag = AppendCRC16($abtSelectTag, 7)
$abtRx = $$(Sprintf("SEND %s", AsHexString($abtSelectTag)))
$abtSak = $abtRx[0]

// Test if we are dealing with a CL2
if($abtSak & $CASCADE_BIT) {
     $szCL = 2
     // Check answer
     if($abtRawUid[0] != 0x88) {
          Printf("WARNING: Cascade bit set but CT != 0x88!\n")
     }
}

// We have to do the anti-collision for cascade level 2:
if(szCL == 2) {

    // Prepare CL2 commands
    $abtSelectAll[0] = 0x95;
    // Anti-collision
    $abtRx = $$(Sprintf("SEND %s", AsHexString($abtSelectAll)))
    // Check answer
    if(($abtRx[0] ^ $abtRx[1] ^ $abtRx[2] ^ $abtRx[3] ^ $abtRx[4]) != 0) {
         Printf("WARNING: BCC check failed!\n");
    }
    // Save UID CL2
    $abtRawUid[4:4] = $abtRx[0:4]
    // Selection
    $abtSelectTag[0] = 0x95;
    $abtSelectTag[2:7] = $abtRx[0:5]
    $abtSelectTag = AppendCRC16($abtSelectTag, 9)
    $abtRx = $$(Sprintf("SEND %s", AsHexString($abtSelectTag)))
    $abtSak = $abtRx[0];
    // Test if we are dealing with a CL3
    if($abtSak & $CASCADE_BIT) {
         $szCL = 3;
         // Check answer
         if($abtRawUid[0] != 0x88) {
              Printf("WARNING: Cascade bit set but CT != 0x88!\n");
         }
    }

    // We have to do the anti-collision for cascade level 3
    if($szCL == 3) {

         // Prepare and send CL3 AC-Command
         $abtSelectAll[0] = 0x97;
         $abtRx = $$(Sprintf("SEND %s", AsHexString($abtSelectAll)))
         // Check answer
         if(($abtRx[0] ^ $abtRx[1] ^ $abtRx[2] ^ $abtRx[3] ^ $abtRx[4]) != 0) {
              Printf("WARNING: BCC check failed!\n");
         }
         // Save UID CL3
         $abtRawUid[8:12] = $abtRx[0:4]
         // Prepare and send final Select-Command
         $abtSelectTag[0] = 0x97;
         $abtSelectTag[2:7] = $abtRx[0:5]
         $abtSelectTag = AppendCRC16($abtSelectTag, 7)
         $abtRx = $$(Sprintf("SEND %s", AsHexString($abtSelectTag)))
         $abtSak = $abtRx[0];
    }

}

// Request ATS (this only applies to tags that support ISO 14443A-4)
if(($abtRx[0] & $SAK_FLAG_ATS_SUPPORTED)) {
    $abtRats = AppendCRC16($abtRats, 2)
    $abtRx = $$(Sprintf("SEND %s", AsHexString($abtRats)))
    if(not $abtRx->isError) {
         $abtAts = $abtRx[0:$szRx]
         $szAts = szRx;
    }
}

// Done, halt the tag now
$abtHalt = AppendCRC16($abtHalt, 2)
$$(Sprintf("SEND %s", AsHexString($abtHalt)))

Printf("| ********************************************************** |\n\n")
Printf("Found tag with\n UID: ");
if($szCL == 1) {
   Printf("%02x%02x%02x%02x", $abtRawUid[0], $abtRawUid[1], $abtRawUid[2], $abtRawUid[3])
}
else if($szCL == 2)
   Printf("%02x%02x%02x",     $abtRawUid[1], $abtRawUid[2], $abtRawUid[3])
   Printf("%02x%02x%02x%02x", $abtRawUid[4], $abtRawUid[5], $abtRawUid[6], $abtRawUid[7])
}
else if($szCL == 3) {
   Printf("%02x%02x%02x",      $abtRawUid[1], $abtRawUid[2], $abtRawUid[3]);
   Printf("%02x%02x%02x",      $abtRawUid[5], $abtRawUid[6], $abtRawUid[7]);
   Printf("%02x%02x%02x%02x",  $abtRawUid[8], $abtRawUid[9], $abtRawUid[10], $abtRawUid[11]);
}
Printf("\n");
Printf("ATQA: %02x%02x\n SAK: %02x\n", $abtAtqa[1], $abtAtqa[0], $abtSak);
if($szAts > 1) {
     Printf("ATS: %s", AsHexString($abtAts, $szAts))
}
Printf("\n| ********************************************************** |\n")

Exit(0)

Thanks for the input and feedback. Sorry for spamming off topic too much here.

maxieds avatar Oct 26 '20 06:10 maxieds

I want to note that this project is still under active development within my app (CMLD). So far the scripting API is semi-tested. I haven't gotten to the point where the nfc-anticol script is a reasonable approximation to what the command line utility does yet. The script at this link is known to work in the most recent versions of the app. I honestly could use some help and/or motivation to finish up more of this project. Is anyone interested in this feature?

maxieds avatar Feb 10 '21 04:02 maxieds