]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdlffdx.c
5677c79dee8ba0a17f7db37f718ea7c9120cabe6
   1 //----------------------------------------------------------------------------- 
   3 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   4 // at your option, any later version. See the LICENSE.txt file for the text of 
   6 //----------------------------------------------------------------------------- 
   7 // Low frequency fdx-b tag commands 
   8 // Differential Biphase, rf/32, 128 bits (known) 
   9 //----------------------------------------------------------------------------- 
  17 #include "ui.h"         // for PrintAndLog 
  19 #include "cmdparser.h" 
  24 #include "protocols.h" 
  28         FDX-B ISO11784/85 demod  (aka animal tag)  BIPHASE, inverted, rf/32,  with preamble of 00000000001 (128bits) 
  29         8 databits + 1 parity (1) 
  31         NATIONAL CODE, ICAR database 
  32         COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf 
  33         FLAG (animal/non-animal) 
  40         16 ccitt CRC chksum over 64bit ID CODE. 
  43         sample: 985121004515220  [ 37FF65B88EF94 ] 
  46 static int CmdHelp(const char *Cmd
); 
  48 int usage_lf_fdx_clone(void){ 
  49         PrintAndLog("Clone a FDX-B animal tag to a T55x7 tag."); 
  50         PrintAndLog("Usage: lf fdx clone [h] <country id> <animal id> <Q5>"); 
  51         PrintAndLog("Options:"); 
  52         PrintAndLog("      h            : This help"); 
  53         PrintAndLog("      <country id> : Country id"); 
  54         PrintAndLog("      <animal id>  : Animal id"); 
  59         PrintAndLog("      <Q5>        : Specify write to Q5 (t5555 instead of t55x7)"); 
  61         PrintAndLog("Sample: lf fdx clone 999 112233"); 
  65 int usage_lf_fdx_sim(void) { 
  66         PrintAndLog("Enables simulation of FDX-B animal tag"); 
  67         PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); 
  69         PrintAndLog("Usage:  lf fdx sim [h] <country id> <animal id>"); 
  70         PrintAndLog("Options:"); 
  71         PrintAndLog("      h            : This help"); 
  72         PrintAndLog("      <country id> : Country ID"); 
  73         PrintAndLog("      <animal id>  : Animal ID"); 
  75         PrintAndLog("Sample: lf fdx sim 999 112233"); 
  78 // clearing the topbit needed for the preambl detection.  
  79 static void verify_values(uint32_t countryid
, uint64_t animalid
){ 
  80         if ((animalid 
& 0x3FFFFFFFFF) != animalid
) { 
  81                 animalid 
&= 0x3FFFFFFFFF; 
  82                 PrintAndLog("Animal ID Truncated to 38bits: %"PRIx64
, animalid
); 
  84         if ( (countryid 
& 0x3ff) != countryid 
) { 
  86                 PrintAndLog("Country ID Truncated to 10bits: %03d", countryid
); 
  90 int getFDXBits(uint64_t national_id
, uint16_t country
, uint8_t isanimal
, uint8_t isextended
, uint32_t extended
, uint8_t *bits
) { 
  93         // every 9th bit is 0x01, but we can just fill the rest with 0x01 and overwrite 
  94         memset(bits
, 0x01, 128); 
  96         // add preamble ten 0x00 and one 0x01 
  97         memset(bits
, 0x00, 10); 
 100         num_to_bytebitsLSBF(0x00, 7, bits 
+ 66); 
 101         num_to_bytebitsLSBF(0x00 >> 7, 7, bits 
+ 74); 
 103         // add animal flag - OK 
 106         // add extended flag - OK 
 107         bits
[81] = isextended
; 
 109         // add national code 40bits - OK 
 110         num_to_bytebitsLSBF(national_id 
>> 0, 8, bits
+11); 
 111         num_to_bytebitsLSBF(national_id 
>> 8, 8, bits
+20); 
 112         num_to_bytebitsLSBF(national_id 
>> 16, 8, bits
+29); 
 113         num_to_bytebitsLSBF(national_id 
>> 24, 8, bits
+38); 
 114         num_to_bytebitsLSBF(national_id 
>> 32, 6, bits
+47); 
 116         // add country code - OK 
 117         num_to_bytebitsLSBF(country 
>> 0, 2, bits
+53); 
 118         num_to_bytebitsLSBF(country 
>> 2, 8, bits
+56); 
 122         for (uint8_t i
=0; i
<8; ++i
) 
 123                 raw
[i
] = bytebits_to_byte(bits 
+ 11 + i 
* 9, 8); 
 125         uint16_t crc 
= crc16_ccitt_kermit(raw
, 8); 
 126         num_to_bytebitsLSBF(crc 
>> 0, 8, bits
+83); 
 127         num_to_bytebitsLSBF(crc 
>> 8, 8, bits
+92); 
 129         // extended data - OK 
 130         num_to_bytebitsLSBF( extended 
>> 0 , 8, bits
+101); 
 131         num_to_bytebitsLSBF( extended 
>> 8 , 8, bits
+110); 
 132         num_to_bytebitsLSBF( extended 
>> 16, 8, bits
+119); 
 136 int CmdFdxDemod(const char *Cmd
){ 
 138         //Differential Biphase / di-phase (inverted biphase) 
 139         //get binary from ask wave 
 140         if (!ASKbiphaseDemod("0 32 1 100", false)) { 
 141                 if (g_debugMode
) PrintAndLog("DEBUG: Error - FDX-B ASKbiphaseDemod failed"); 
 144         size_t size 
= DemodBufferLen
; 
 145         int preambleIndex 
= FDXBdemodBI(DemodBuffer
, &size
); 
 146         if (preambleIndex 
< 0){ 
 148                         if (preambleIndex 
== -1) 
 149                                 PrintAndLog("DEBUG: Error - FDX-B too few bits found"); 
 150                         else if (preambleIndex 
== -2) 
 151                                 PrintAndLog("DEBUG: Error - FDX-B preamble not found"); 
 152                         else if (preambleIndex 
== -3) 
 153                                 PrintAndLog("DEBUG: Error - FDX-B Size not correct: %d", size
); 
 155                                 PrintAndLog("DEBUG: Error - FDX-B ans: %d", preambleIndex
); 
 160         // set and leave DemodBuffer intact 
 161         setDemodBuf(DemodBuffer
, 128, preambleIndex
); 
 162         setClockGrid(g_DemodClock
, g_DemodStartIdx 
+ (preambleIndex
*g_DemodClock
)); 
 164         uint8_t bits_no_spacer
[117]; 
 165         memcpy(bits_no_spacer
, DemodBuffer 
+ 11, 117); 
 167         // remove marker bits (1's every 9th digit after preamble) (pType = 2) 
 168         size 
= removeParity(bits_no_spacer
, 0, 9, 2, 117); 
 170                 if (g_debugMode
) PrintAndLog("DEBUG: Error removeParity:: %d", size
); 
 175         uint64_t NationalCode 
= ((uint64_t)(bytebits_to_byteLSBF(bits_no_spacer
+32,6)) << 32) | bytebits_to_byteLSBF(bits_no_spacer
,32); 
 176         uint32_t countryCode 
= bytebits_to_byteLSBF(bits_no_spacer
+38,10); 
 177         uint8_t dataBlockBit 
= bits_no_spacer
[48]; 
 178         uint32_t reservedCode 
= bytebits_to_byteLSBF(bits_no_spacer
+49,14); 
 179         uint8_t animalBit 
= bits_no_spacer
[63]; 
 180         uint32_t crc16 
= bytebits_to_byteLSBF(bits_no_spacer
+64,16); 
 181         uint32_t extended 
= bytebits_to_byteLSBF(bits_no_spacer
+80,24); 
 183         uint64_t rawid 
= ((uint64_t)bytebits_to_byte(bits_no_spacer
,32)<<32) | bytebits_to_byte(bits_no_spacer
+32,32); 
 185         num_to_bytes(rawid
, 8, raw
); 
 188                 PrintAndLog("DEBUG: bits_no_spacer:\n%s",sprint_bin_break(bits_no_spacer
,size
,16)); 
 189                 PrintAndLog("DEBUG: Start marker %d;   Size %d", preambleIndex
, size
); 
 190                 PrintAndLog("DEBUG: Raw ID Hex: %s", sprint_hex(raw
,8)); 
 193         uint16_t calcCrc 
= crc16_ccitt_kermit(raw
, 8); 
 194         PrintAndLog("\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); 
 195         PrintAndLog("Animal ID:     %04u-%012" PRIu64
, countryCode
, NationalCode
); 
 196         PrintAndLog("National Code: %012" PRIu64
, NationalCode
); 
 197         PrintAndLog("CountryCode:   %04u", countryCode
); 
 198         PrintAndLog("Reserved Code: %u", reservedCode
); 
 199         PrintAndLog("Animal Tag:    %s", animalBit 
? "True" : "False"); 
 200         PrintAndLog("Has Extended:  %s [0x%X]", dataBlockBit 
? "True" : "False", extended
); 
 201         PrintAndLog("CRC:           0x%04X - 0x%04X - [%s]\n", crc16
, calcCrc
, (calcCrc 
== crc16
) ? "Passed" : "Failed"); 
 203         // set block 0 for later 
 204         //g_DemodConfig = T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT; 
 208 int CmdFdxRead(const char *Cmd
) { 
 209         lf_read(true, 10000); 
 210         return CmdFdxDemod(Cmd
); 
 213 int CmdFdxClone(const char *Cmd
) { 
 215         uint32_t countryid 
= 0; 
 216         uint64_t animalid 
= 0; 
 217         uint32_t blocks
[5] = {T55x7_MODULATION_DIPHASE 
| T55x7_BITRATE_RF_32 
| 4 << T55x7_MAXBLOCK_SHIFT
, 0, 0, 0, 0}; 
 220         memset(bs
, 0, sizeof(bits
)); 
 222         char cmdp 
= param_getchar(Cmd
, 0); 
 223         if (strlen(Cmd
) == 0 || cmdp 
== 'h' || cmdp 
== 'H') return usage_lf_fdx_clone(); 
 225         countryid 
= param_get32ex(Cmd
, 0, 0, 10); 
 226         animalid 
= param_get64ex(Cmd
, 1, 0, 10); 
 229         if (param_getchar(Cmd
, 2) == 'Q' || param_getchar(Cmd
, 2) == 'q') { 
 230                 //t5555 (Q5) BITRATE = (RF-2)/2 (iceman) 
 231                 blocks
[0] = T5555_MODULATION_BIPHASE 
| T5555_INVERT_OUTPUT 
| ((32-2)>>1) << T5555_BITRATE_SHIFT 
| 4 << T5555_MAXBLOCK_SHIFT
; 
 234         verify_values(countryid
, animalid
); 
 236         // getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits)  
 237         if ( !getFDXBits(animalid
, countryid
, 1, 0, 0, bs
)) { 
 238                 PrintAndLog("Error with tag bitstream generation."); 
 242         // convert from bit stream to block data 
 243         blocks
[1] = bytebits_to_byte(bs
,32); 
 244         blocks
[2] = bytebits_to_byte(bs
+32,32); 
 245         blocks
[3] = bytebits_to_byte(bs
+64,32); 
 246         blocks
[4] = bytebits_to_byte(bs
+96,32); 
 248         PrintAndLog("Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64
, countryid
, animalid
); 
 249         PrintAndLog("Blk | Data "); 
 250         PrintAndLog("----+------------"); 
 251         PrintAndLog(" 00 | 0x%08x", blocks
[0]); 
 252         PrintAndLog(" 01 | 0x%08x", blocks
[1]); 
 253         PrintAndLog(" 02 | 0x%08x", blocks
[2]); 
 254         PrintAndLog(" 03 | 0x%08x", blocks
[3]); 
 255         PrintAndLog(" 04 | 0x%08x", blocks
[4]); 
 258         UsbCommand c 
= {CMD_T55XX_WRITE_BLOCK
, {0,0,0}}; 
 260         for (int i 
= 4; i 
>= 0; --i
) { 
 261                 c
.arg
[0] = blocks
[i
]; 
 263                 clearCommandBuffer(); 
 265                 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, T55XX_WRITE_TIMEOUT
)){ 
 266                         PrintAndLog("Error occurred, device did not respond during write operation."); 
 273 int CmdFdxSim(const char *Cmd
) { 
 274         uint32_t countryid 
= 0; 
 275         uint64_t animalid 
= 0; 
 277         char cmdp 
= param_getchar(Cmd
, 0); 
 278         if (strlen(Cmd
) == 0 || cmdp 
== 'h' || cmdp 
== 'H') return usage_lf_fdx_sim(); 
 280         countryid 
= param_get32ex(Cmd
, 0, 0, 10); 
 281         animalid 
= param_get64ex(Cmd
, 1, 0, 10); 
 283         verify_values(countryid
, animalid
); 
 285         uint8_t clk 
= 32, encoding 
= 2, separator 
= 0, invert 
= 1; 
 288         arg1 
= clk 
<< 8 | encoding
; 
 289         arg2 
= invert 
<< 8 | separator
; 
 291         PrintAndLog("Simulating FDX-B animal ID: %04u-%"PRIu64
, countryid
, animalid
); 
 293         UsbCommand c 
= {CMD_ASK_SIM_TAG
, {arg1
, arg2
, size
}}; 
 295          //getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits)  
 296         getFDXBits(animalid
, countryid
, 1, 0, 0, c
.d
.asBytes
); 
 297         clearCommandBuffer(); 
 302 static command_t CommandTable
[] = { 
 303         {"help",  CmdHelp
,    1, "This help"}, 
 304         {"demod", CmdFdxDemod
,1, "Attempt to extract FDX-B ISO11784/85 data from the GraphBuffer"}, 
 305         {"read",  CmdFdxRead
, 0, "Attempt to read and extract FDX-B ISO11784/85 data"}, 
 306         {"clone", CmdFdxClone
,0, "Clone animal ID tag to T55x7 (or to q5/T5555)"}, 
 307         {"sim",   CmdFdxSim
,  0, "Animal ID tag simulator"}, 
 308         {NULL
, NULL
, 0, NULL
} 
 311 int CmdLFFdx(const char *Cmd
) { 
 312         clearCommandBuffer(); 
 313         CmdsParse(CommandTable
, Cmd
); 
 317 int CmdHelp(const char *Cmd
) { 
 318         CmdsHelp(CommandTable
);