// update hitag1 crc for arbitrary binarray length void hitag1_binarray_crc(BYTE *crc, BYTE *bin, BYTE length) { BYTE i; for(i= 0 ; i < length ; i += 8) if(length - i < 8) hitag1_crc(crc, (BYTE) binarraytoint(bin + i, length - i) << 8 - (length - i), length - i); else hitag1_crc(crc, (BYTE) binarraytoint(bin + i, 8), 8); }
// convert human readable UID to 128 bit fdx-b binary array BOOL uid_to_hdx_bin(BYTE *bin, BYTE *uid) { BYTE tmp1[64], crc[8], i; unsigned int country, crctag; unsigned long long id; memset(tmp1, 0x00, 64); // set animal flag if(uid[0] == 'A') tmp1[0]= 0x01; else if(uid[0] != '0') return FALSE; // set data flag if(uid[1] == 'D') tmp1[15]= 0x01; else if(uid[1] != '0') return FALSE; // set country code - 4 hex digits -> 10 bits country= bcdtouint(uid + 2, 4); inttobinarray(tmp1 + 16, country, 10); // set national ID - 12 hex digits -> 38 bits id= bcdtoulonglong(uid + 6, 12); ulonglongtobinarray(tmp1 + 26, id, 38); // reverse binary string_reverse(tmp1, 64); // add header for over-the-air: 10 x 0x00 + 0x01 memset(bin, 0x00, 10); // every 9th bit is 0x01, but we can just fill the rest with 0x01 and overwrite memset(bin + 10, 0x01, 118); //data is 8 blocks of 8 bits, plus obfuscation bit for(i= 0 ; i < 8 ; ++i) memcpy(bin + 11 + i * 9, tmp1 + i * 8, 8); // calculate & append crc for 64 bits of data for(i= 0 ; i < 8 ; ++i) crc[i]= (BYTE) binarraytoint(tmp1 + i * 8, 8); crctag= crc_ccitt(crc, 8); inttobinarray(bin + 83, crctag >> 8, 8); inttobinarray(bin + 92, crctag, 8); // add trailer for(i= 0 ; i < 3 ; ++i) memset(bin + 101 + i * 9, 0x00, 8); return TRUE; }
// convert 32 hex digit/128 bit FDXB ID to 64 bit raw UID // safe to do in-place as we use a scratchpad BOOL hdx_hex_to_bin(BYTE *response, BYTE *fdxb) { BYTE i, crc_check[8], trailer[9]= {0,0,0,0,0,0,0,0,1}, tmp[128]; unsigned int crctag; hextobinarray(tmp, fdxb); // check header - should be 10 x 0x00 + 0x01 for(i= 0 ; i < 10 ; ++i) if(tmp[i] != 0x00) return FALSE; if(tmp[10] != 0x01) return FALSE; // check CRC // calculate crc for 64 bits of data (8 blocks of 8 plus obfuscation bit) for(i= 0 ; i < 8 ; ++i) crc_check[i]= (BYTE) binarraytoint(tmp + 11 + i * 9, 8); // stored crc (2 x 8 + 1) is at offset 83 (11 + 64 + 8) crctag= binarraytoint(tmp + 83, 8) << 8; crctag += binarraytoint(tmp + 92, 8); if (crctag != crc_ccitt(crc_check, 8)) return FALSE; // check trailer - '000000001' x 3 at offset 101 for(i= 0 ; i < 3 ; ++i) if(memcmp(tmp + 101 + i * 9, trailer, 9) != 0) return FALSE; // data is 8 blocks of 8 bits, plus obfuscation bit so check and strip every 9th bit for(i= 0 ; i < 8 ; ++i) { if(tmp[11 + ((i + 1) * 9) - 1] != 0x01) return FALSE; memcpy(response + i * 8, tmp + 11 + (i * 9), 8); } return TRUE; }
// convert fdxb 128 bit binary array to human readable UID // format is ADCCCCIIIIIIIIIIII where A is 'A' or '0' for animal / non-animal, // D is 'D' or '0' for Data block available / No data available, // CCCC is ISO-3166 country code or ICAR.ORG manufacturer code // IIIIIIIIIIII is national ID BOOL hdx_hex_to_uid(BYTE *uid, BYTE *hex) { BYTE tmp[128]; unsigned int country; unsigned long long id; // strip headers etc. if(!fdxb_hex_to_bin(tmp, hex)) return FALSE; // reverse binary string_reverse(tmp, 64); // output animal flag if(tmp[0]) uid[0]= 'A'; else uid[0]= '0'; // output data flag if(tmp[15]) uid[1]= 'D'; else uid[1]= '0'; // output country/icar code country= binarraytoint(&tmp[16], 10); sprintf(&uid[2], "%04u", country); // output national ID id= binarraytoulonglong(&tmp[26], 38); sprintf(&uid[6], "%012llu", id); return TRUE; }