// auth in password mode BOOL hitag2_pwd_auth(BYTE *response, BYTE *pwd) { BYTE tmp[37]; // restart the tag if(!hitag2_get_uid(tmp)) return FALSE; if(strlen(pwd) == 0) pwd= HITAG2_PWD_DEFAULT; // use default transport key if none specified if(!hextobinstring(tmp, pwd)) return FALSE; // wait for RX->TX period, then send 32 bit PWD if(!rwd_send(tmp, strlen(tmp), NO_RESET, BLOCK, RWD_STATE_WAKING, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) return FALSE; // skip 1/2 bit to synchronise manchester HW_Skip_Bits= 1; // get 37 bit response: sync + config byte + 24 bit TAG pwd if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY) == 37) { // check sync bits if (memcmp(tmp, Hitag2Sync, 5) != 0) return FALSE; binarraytohex(response, tmp + 5, 32); return TRUE; } return FALSE; }
BOOL get_tag_uid(BYTE *response) { switch(RFIDlerConfig.TagType) { case TAG_TYPE_ASK_RAW: return ask_raw_get_uid(response); case TAG_TYPE_AWID_26: return awid26_get_uid(response); case TAG_TYPE_EM4X02: return em4x02_get_uid(response); case TAG_TYPE_FDXB: return fdxb_get_uid(response); case TAG_TYPE_FSK1_RAW: case TAG_TYPE_FSK2_RAW: return fsk_raw_get_uid(response); case TAG_TYPE_HID_26: return hid26_get_uid(response); case TAG_TYPE_HITAG1: return hitag1_get_uid(response); case TAG_TYPE_HITAG2: return hitag2_get_uid(response); case TAG_TYPE_INDALA_64: return indala64_get_uid(response); case TAG_TYPE_INDALA_224: return indala224_get_uid(response); case TAG_TYPE_PSK1_RAW: return psk1_raw_get_uid(response); case TAG_TYPE_Q5: //case TAG_TYPE_T55X7: return q5_get_uid(response); case TAG_TYPE_UNIQUE: return unique_get_uid(response); default: break; } return FALSE; }
// attempt to find ideal parameters for GAP, ZERO and ONE periods. // ranges specified in FC void hitag2_test_rwd(unsigned int gapmin, unsigned int gapmax, unsigned int zeromin, unsigned int zeromax, unsigned int onemin, unsigned int onemax, BYTE *pass) { BYTE i, imax, countu, counta, countr; unsigned int gap, zero, one, fc; imax= 5; for(fc= 800 ; fc <= 809 ; ++fc) { for(gap= gapmin ; gap <= gapmax ; ++gap) for(zero= zeromin ; zero <= zeromax ; ++zero) for(one= onemin ; one <= onemax ; ++one) { RFIDlerConfig.FrameClock= (unsigned long) fc; RFIDlerConfig.RWD_Gap_Period= gap; RFIDlerConfig.RWD_Zero_Period= zero; RFIDlerConfig.RWD_One_Period= one; UserMessageNum("\rGap %d", gap); UserMessageNum(" Zero %d", zero); UserMessageNum(" One %d", one); UserMessageNum(" FC %d", fc); for(i= countu= counta= countr= 0 ; i < imax ; ++i) { if(get_user_abort()) return; if(hitag2_get_uid(DataBuff)) { ++countu; if(hitag2_pwd_auth(DataBuff, pass) || hitag2_crypto_auth(DataBuff, pass)) { ++counta; if(hitag2_read_page(DataBuff, 0)) ++countr; } } } if(countu == imax && counta == imax && countr == imax) { UserMessageNum(" - got %d", countu); UserMessageNum(" uids, %d", counta); UserMessageNum(" auths %d", countr); UserMessageNum(" reads, out of %d attempts.\r\n", imax); } } UserMessage("%s", "\r\n"); } }
// note that PRN is not created with security in mind - just using a simple seed BOOL hitag2_crypto_auth(BYTE *response, BYTE *hexkey) { BYTE tmp[65], tmphex[9]; unsigned long long key; unsigned long uid; unsigned long initvec; // use default transport key if none specified if(strlen(hexkey) == 0) hexkey= HITAG2_KEY_DEFAULT; // get UID for initialisation if(!hitag2_get_uid(tmp)) return FALSE; // convert to numerics for crypto routines uid= hexreversetoulong(tmp); key= hexreversetoulonglong(hexkey); // generate 32 bit PRN for challenge srand(Led_Count); initvec= rand(); initvec <<= 16; initvec += rand(); // prepare to send IV in the clear to tag ulongtobinstring(tmp, initvec, 32); // convert IV to MSB for crypto routines binstringtohex(tmphex, tmp); initvec= hexreversetoulong(tmphex); // initialise crypto hitag2_init(&Hitag_Crypto_State, rev64(key), rev32(uid), rev32(initvec)); // send inverse of 1st 32bits of keystream to tag for authentication ulongtobinstring(tmp + 32, hitag2_crypt(0xFFFFFFFF, 32), 32); // restart the tag & auth process if(!hitag2_get_uid(TmpBuff)) return FALSE; // wait for RX->TX period, then send PRN+secret if(!rwd_send(tmp, strlen(tmp), NO_RESET, BLOCK, RWD_STATE_WAKING, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) return FALSE; // skip 1/2 bit to synchronise manchester HW_Skip_Bits= 1; // get 37 bit response: sync + config byte + 24 bit TAG pwd if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY) == 37) { // check sync bits if (memcmp(tmp, Hitag2Sync, 5) != 0) return FALSE; CryptoActive= TRUE; // decrypt binarraytohex(response, tmp + 5, 32); return hitag2_hex_crypt(response, response); } return FALSE; }