void xml_header(BYTE *item, BYTE *indent) { UserMessage("%s", "\r\n"); space_indent(*indent); UserMessage("<%s>", item); (*indent) += 2; }
// send end of data void eod(void) { if(Interface == INTERFACE_API) UserMessage("%s", "*\r\n"); else UserMessage("%s", "\r\n"); }
// try to find values that correctly transmit all commands to t55x7 // so that a GET_UID command will return a true value BOOL t55x7_rwd_test(BYTE *pattern) { BYTE gap, one, zero, i, tmp[T55X7_BLOCKSIZE * 2 + 1]; BOOL found= FALSE; // min/max from datasheets for(one= 48 ; one <= 63 ; ++one) for(zero= 16; zero <= 31 ; ++zero) for(gap= 8 ; gap <= 30 ; ++gap) { if(get_user_abort()) return found; RFIDlerConfig.RWD_Gap_Period= gap; RFIDlerConfig.RWD_One_Period= one; RFIDlerConfig.RWD_Zero_Period= zero; if(get_tag_uid(tmp)) { UserMessageNum(" gap: %d", gap); UserMessageNum(" one: %d", one); UserMessageNum(" zero: %d", zero); UserMessage(" UID: %s\r\n", tmp); found= TRUE; } } UserMessage("%s", "\r\n"); return found; }
// command NACK when in API mode // note we still return TRUE to flag CLI that command was recognised BOOL command_nack(BYTE *reason) { if(Interface == INTERFACE_API) UserMessage("!%s\r\n", reason); else UserMessage("\r\n%s\r\n\r\n", reason); return TRUE; }
void tag_list(void) { unsigned char i; UserMessage("%s", "\r\nKnown TAG types:\r\n"); for(i= 1 ; TagTypes[i] != NULL ; ++i) { UserMessage("\r\n %s", (BYTE *) TagTypes[i]); } UserMessage("%s", "\r\n"); }
void xml_footer(BYTE *item, BYTE *indent, BOOL newline) { if(newline) UserMessage("%s", "\r\n"); if(*indent > 1) (*indent) -= 2; else *indent= 0; if(newline) space_indent(*indent); UserMessage("</%s>", item); }
BYTE get_prompt(unsigned char *prompt) { BYTE tmp; UserMessage("\r\n%s and hit <RETURN> to continue, or any other key to abort...", prompt); while(42) if (GetUserMessage(&tmp, 1)) { UserMessage("%s", "\r\n"); return (tmp == '\r'); } }
// SendCommand // Pops up a Custinfo dialog or sends an exit command to Custinfo // Assumptions: // Custinfo is running. For a dialog, either the account is // specified in the call or the correct account is already open in // Custinfo. // Returns: // TRUE if able to post the message. // FALSE if failed to post the message. // Error messages: // Internal error message when function returns FALSE. // Side affects: // Pops up a Custinfo dialog or exits Custinfo. BOOL CCustinfoDriverApp::SendCommand(CArborCommandLineInfo::Flag flag) { UINT message; if (flag == CArborCommandLineInfo::dialog) { if (!m_CmdInfo.m_sAccountid.IsEmpty() && !OpenAccount()) { return FALSE; } message = GetDialogMessage(); } else if (flag == CArborCommandLineInfo::exit) { message = ci_ipc::uAPP_EXIT; } else { ErrorMessage(__FILE__, __LINE__, "Unknown command."); return FALSE; } if (!ci_ipc::FindCustInfo()) { if (flag != CArborCommandLineInfo::exit) { if (m_CmdInfo.m_sUsermessage.IsEmpty()) { UserMessage(m_sUsermessage); } else { UserMessage(m_CmdInfo.m_sUsermessage); } } return FALSE; } if (!ci_ipc::DoIPC(message)) { if (flag != CArborCommandLineInfo::exit) { ErrorMessage(__FILE__, __LINE__, "Unable to process request."); } return FALSE; } return TRUE; }
void decode_pwm(unsigned long pulses[], unsigned long gaps[], unsigned int count) { unsigned int i; switch(RFIDlerConfig.TagType) { case TAG_TYPE_HITAG1: hitag1_decode_pwm(pulses, gaps, count); break; case TAG_TYPE_HITAG2: hitag2_decode_pwm(pulses, gaps, count); break; case TAG_TYPE_Q5: case TAG_TYPE_T55X7: q5_decode_pwm(pulses, gaps, count); break; case TAG_TYPE_TAMAGOTCHI: tamagotchi_decode_pwm(pulses, gaps, count); break; default: for(i= 0 ; i < count ; ++i) { UserMessageNum("\r\nPulse: %d ", pulses[i]); UserMessageNum("Gap: %d", gaps[i]); } break; } UserMessage("\r\n",""); }
void space_indent(BYTE count) { while(count) { UserMessage("%s", " "); --count; } }
BYTE auto_detect_tag_type(void) { BYTE i, tag, tmp[MAXUID + 1]; tag= RFIDlerConfig.TagType; UserMessage("%s", "\r\n"); for(i= 1 ; TagTypes[i] != NULL ; ++i) { UserMessage("\r\n %s: ", (BYTE *) TagTypes[i]); tag_set(i); if(get_interpreted_tag_uid(tmp, RFIDlerConfig.TagType)) UserMessage("%s", tmp); } tag_set(tag); UserMessage("%s", "\r\n"); }
// OpenAccount // Opens an account in Custinfo dialog. // Assumptions: // Custinfo is running. // Returns: // TRUE if able to post the account_id. // FALSE if failed to post the account_id. // Error messages: // CSR error message when unable to tell Custinfo to open an // account. Internal error message for any other reason for this // function to return FALSE. // Side affects: // Opens an account in Custinfo. BOOL CCustinfoDriverApp::OpenAccount() { if (ci_ipc::FindCustInfo()) { if (m_CmdInfo.AccountIdTypeIsEmpty()) { if (!ci_ipc::ActivateAccount(m_CmdInfo.m_sAccountid)) { ErrorMessage(__FILE__, __LINE__, "Open account failed. Account_id: ", m_CmdInfo.m_sAccountid); return FALSE; } } else { int AccountIdType; m_CmdInfo.GetAccountIdType(AccountIdType); if (!ci_ipc::ActivateAccount(m_CmdInfo.m_sAccountid, AccountIdType)) { CString message; message.Format("Open account failed. Account_id: %s, Account_id_type: %d.", m_CmdInfo.m_sAccountid, AccountIdType); ErrorMessage(__FILE__, __LINE__, message); return FALSE; } } } else { if (m_CmdInfo.m_sUsermessage.IsEmpty()) { UserMessage(m_sUsermessage); } else { UserMessage(m_CmdInfo.m_sUsermessage); } return FALSE; } return TRUE; }
// command ACK when in API mode // '.' for command complete // '+' for data to follow BOOL command_ack(BOOL data) { if(Interface == INTERFACE_API) { if(data) UserMessage("%s", "+"); else UserMessage("%s", "."); } else { if(data) UserMessage("%s", "\r\n"); else UserMessage("%s", "\r\nOK\r\n\r\n"); } return TRUE; }
void UserMessageNum(BYTE *message, unsigned long num) { BYTE tmp[TMP_SMALL_BUFF_LEN]; sprintf(tmp, message, num); if(CommsChannel == COMMS_USB) UserMessage("%s", tmp); }
void xml_item_decimal(BYTE *item, BYTE num, BYTE *indent) { BYTE tmp[4]; xml_header(item, indent); sprintf(tmp, "%d", num); UserMessage("%s", tmp); xml_footer(item, indent, NO_NEWLINE); }
void debug_show(void) { BYTE i; for(i= 1 ; i < 5 ; ++i) { UserMessageNum("Debug pin %d: ", i); UserMessage("%s\r\n", debug_get(i) ? "OFF" : "ON"); } }
/// show contents of vtag void vtag_dump(void) { BYTE tmp[MAXBLOCKSIZE + 1], interpret; unsigned int i; UserMessage(" Type: %s", (BYTE *) TagTypes[RFIDlerVTag.TagType]); UserMessage("\r\n Emulating: %s", (BYTE *) TagTypes[RFIDlerVTag.EmulatedTagType]); UserMessage("\r\n Raw UID: %s", RFIDlerVTag.UID); // show interpreted UID if(RFIDlerVTag.EmulatedTagType == TAG_TYPE_NONE) interpret= RFIDlerVTag.TagType; else interpret= RFIDlerVTag.EmulatedTagType; UserMessage("\r\n UID: %s", interpret_uid(tmp, RFIDlerVTag.UID, interpret) ? tmp : (BYTE *) "invalid!"); // show config block if present if(config_block_number(&i, RFIDlerVTag.TagType)) { UserMessage("%s","\r\n\r\n"); config_block_show(&RFIDlerVTag.Data[HEXDIGITS(RFIDlerVTag.BlockSize * i)], RFIDlerVTag.TagType); } if(RFIDlerVTag.DataBlocks == 0) { UserMessage("%s", "\r\n\r\n"); return; } UserMessage("%s", "\r\n Data:"); tmp[HEXDIGITS(RFIDlerVTag.BlockSize)]= '\0'; for(i= 0 ; i < RFIDlerVTag.DataBlocks ; ++i) { memcpy(tmp, &RFIDlerVTag.Data[HEXDIGITS(RFIDlerVTag.BlockSize * i)], HEXDIGITS(RFIDlerVTag.BlockSize)); if(tmp[0]) { UserMessageNum("\r\n %d: ", i); UserMessage("%s", tmp); } } UserMessage("%s", "\r\n\r\n"); }
void xml_indented_array(BYTE *data, BYTE mask, unsigned int length, BYTE indent) { unsigned int i; for(i= 0 ; i < length ; ++i) { if(!(i % 32)) { UserMessage("%s", "\r\n"); space_indent(indent); } UserMessageNum("%02lx", data[i] & mask); } }
void printbinarray(unsigned char *bin, unsigned int length) { while(length--) { // normally we are printing 0/1, but if we're looking at anything else we want a space between values if(*bin > 1) UserMessageNum("%d ",*bin); else UserMessageNum("%d",*bin); bin++; } UserMessage("%s", "\r\n"); }
void hitag2_pwm_display_nrars() { uint32_t count; uint32_t index; int i; BYTE tmp[20]; memcpy(&count, (void *)HITAG2_PWM_NVM_ADDRESS, 4); UserMessage("%s", "\r\n"); if (count == 0) { UserMessage("%s", "No HiTag2 PWM stored\r\n"); return; } if (count > HITAG2_PWM_NVM_MAX) { UserMessage("%s", "Count overflow\r\n"); return; } tmp[8] = 0x00; for (index=0; index<count; index++) { // UserMessage("nRaR number %d\r\n", index); // memcpy(tmp, (BYTE *)HITAG2_PWM_NVM_DATA + (index * 20), 20); memcpy(tmp, (BYTE *)HITAG2_PWM_NVM_DATA + (index * 20), 8); tmp[8] = ' '; memcpy(tmp + 9, (BYTE *)HITAG2_PWM_NVM_DATA + (index * 20) + 8, 8); tmp[17] = 0x00; UserMessage("%s\r\n", tmp); } return; }
BOOL q5_config_block_show(BYTE *config, BYTE *password) { uint32_t value= hextoulong(config); UserMessage(" Config Block (0): %.8s\r\n\r\n", config); UserMessage(" Page Select: %s\r\n", GET_CONFIG(value, Q5_MASK_PAGE_SELECT, Q5_SHIFT_PAGE_SELECT) ? "True" : "False"); UserMessage(" Fast Write: %s\r\n", GET_CONFIG(value, Q5_MASK_FAST_WRITE, Q5_SHIFT_FAST_WRITE) ? "True" : "False"); UserMessageNum(" Data Rate: %02d = ", GET_CONFIG(value, Q5_MASK_DATA_BIT_RATE, Q5_SHIFT_DATA_BIT_RATE)); UserMessageNum("%d * FC\r\n", GET_CONFIG(value, Q5_MASK_DATA_BIT_RATE, Q5_SHIFT_DATA_BIT_RATE) * 2 + 2); UserMessage(" Use AOR: %s\r\n", GET_CONFIG(value, Q5_MASK_USE_AOR, Q5_SHIFT_USE_AOR) ? "True" : "False"); UserMessage(" Use PWD: %s\r\n", GET_CONFIG(value, Q5_MASK_USE_PWD, Q5_SHIFT_USE_PWD) ? "True" : "False"); UserMessageNum(" PSK Carrier: %d = ", GET_CONFIG(value, Q5_MASK_PSK_CARRIER_FREQ, Q5_SHIFT_PSK_CARRIER_FREQ)); UserMessageNum("%d * FC\r\n", PSK_Rates[GET_CONFIG(value, Q5_MASK_PSK_CARRIER_FREQ, Q5_SHIFT_PSK_CARRIER_FREQ)]); UserMessage(" Inverse Data: %s\r\n", GET_CONFIG(value, Q5_MASK_INVERSE_DATA, Q5_SHIFT_INVERSE_DATA) ? "True" : "False"); UserMessageNum(" Modulation: %d = ", GET_CONFIG(value, Q5_MASK_MODULATION, Q5_SHIFT_MODULATION)); UserMessage("%s\r\n", (BYTE *) Q5_Modulation[GET_CONFIG(value, Q5_MASK_MODULATION, Q5_SHIFT_MODULATION)]); UserMessageNum(" Max Block: %d\r\n", GET_CONFIG(value, Q5_MASK_MAX_BLOCK, Q5_SHIFT_MAX_BLOCK)); UserMessage(" ST: %s\r\n", GET_CONFIG(value, Q5_MASK_ST, Q5_SHIFT_ST) ? "True" : "False"); UserMessage("\r\n PWD Block (7): %.8s ", password); printhexreadable(password, 4); UserMessage("%s", "\r\n"); return TRUE; }
// decode externally sniffed PWM BOOL q5_decode_pwm(unsigned long pulses[], unsigned long gaps[], unsigned int count) { unsigned int i, j; BOOL decoded= FALSE; BYTE out[65]; // max response from hitag2 is 64 bits j= 0; while(j < count) { i= generic_decode_pwm(out, &pulses[j], 10, 512, &gaps[j], 20, 500, count - j); if(i) { decoded= TRUE; UserMessage("\r\n%s", out); j += i; } else break; } UserMessage("%s", "\r\n"); return decoded; }
// 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"); } }
// StartApp // Formats a command line and then runs the application. // Returns: // value returned by CreateProcess // Error messages: // Internal error message when CreateProcess returns FALSE. // Side affects: // Runs application. BOOL CCustinfoDriverApp::StartApp() { TCHAR Process[256]; FormatAppCommandLine(); ASSERT(!m_sAppCommandLine.IsEmpty()); sprintf((LPTSTR)Process, "%s", m_sAppCommandLine); BOOL bCreateStatus = FALSE; STARTUPINFO NewStartInfo; PROCESS_INFORMATION NewProcInfo; memset(&NewStartInfo, 0, sizeof(NewStartInfo)); /* set startup info... */ NewStartInfo.dwFlags = STARTF_USESHOWWINDOW; NewStartInfo.wShowWindow = SW_SHOW; NewStartInfo.cb = sizeof(NewStartInfo); if (m_CmdInfo.m_bShowcommandline) { UserMessage(Process); } bCreateStatus = CreateProcess( NULL, // module to start (LPTSTR) Process, // command line NULL, // process security_attributes NULL, // thread security attributes FALSE, // nprocess inherits handles? 0, // creation flags NULL, // environment block NULL, // drive and dir spec for process &NewStartInfo, // new process start info &NewProcInfo); // new process info if (!bCreateStatus) { ErrorMessage(__FILE__, __LINE__, "\nApplication failed to start.\n", m_sAppCommandLine); } return bCreateStatus; }
// try to find values that correctly transmit all commands to q5 // to test this properly, q5 should have invalid data in it's data blocks // so that only a GET_TRACE_DATA command will return a true value BOOL q5_rwd_test(BYTE *pattern) { BYTE start_gap, gap, one, zero, i, tmp[Q5_BLOCKSIZE + 1]; BOOL found= FALSE, blank; // min/max from datasheets for(one= 48 ; one <= 63 ; ++one) for(zero= 16; zero <= 31 ; ++zero) for(gap= 10 ; gap <= 50 ; ++gap) for(start_gap= 11 ; start_gap <= 50 ; ++start_gap) { RFIDlerConfig.Manchester= TRUE; blank= TRUE; if(get_user_abort()) return found; RFIDlerConfig.RWD_Gap_Period= gap; RFIDlerConfig.RWD_One_Period= one; RFIDlerConfig.RWD_Zero_Period= zero; // reset tag get_tag_uid(tmp); // try to switch off modulation // send command with start gap: reset with sleep time set to start gap, and wake time set to 0 as we transmit the 1st bit immediately // note that we must also subtract standard gap period as it will be added to the front of the first bit by default. rwd_send(Q5_MODULATION_DEFEAT, strlen(Q5_MODULATION_DEFEAT), NO_RESET, BLOCK, RWD_STATE_START_SEND, RFIDlerConfig.FrameClock, start_gap - RFIDlerConfig.RWD_Gap_Period, 0, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX); // read a block with no sync & no manchester - will be all '0' if not modulating RFIDlerConfig.Manchester= FALSE; if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, RFIDlerConfig.DataBits, RFIDlerConfig.Sync, 0, RFIDlerConfig.Timeout, NO_ONESHOT_READ, HEX) == RFIDlerConfig.DataBits) { for(i= 0 ; i < HEXDIGITS(RFIDlerConfig.DataBits) ; ++i) if(tmp[i] != '0') blank= FALSE; RFIDlerConfig.Manchester= TRUE; if(blank && get_tag_uid(tmp) && q5_read_block(tmp, 0)) { UserMessageNum("\r\nFound tag with start_gap %d", start_gap); UserMessageNum(" gap %d", gap); UserMessageNum(" one %d", one); UserMessageNum(" zero %d", zero); found= TRUE; } } } UserMessage("%s", "\r\n"); return found; }
// try to find values that correctly transmit all commands to q5 // to test this properly, q5 should have invalid data in it's data blocks // so that only a GET_TRACE_DATA command will return a true value BOOL q5_rwd_test(BYTE *pattern) { BYTE gap, one, zero, tmp[Q5_BLOCKSIZE + 1]; BOOL found= FALSE, blank; // min/max from datasheets for(one= 48 ; one <= 63 ; ++one) for(zero= 16; zero <= 31 ; ++zero) for(gap= 10 ; gap <= 50 ; ++gap) { RFIDlerConfig.Manchester= TRUE; blank= TRUE; if(get_user_abort()) return found; RFIDlerConfig.RWD_Gap_Period= gap; RFIDlerConfig.RWD_One_Period= one; RFIDlerConfig.RWD_Zero_Period= zero; // reset tag get_tag_uid(tmp); // try to switch off modulation rwd_send(Q5_MODULATION_DEFEAT, strlen(Q5_MODULATION_DEFEAT), NO_RESET, BLOCK, RWD_STATE_START_SEND, RFIDlerConfig.FrameClock, RFIDlerConfig.RWD_Gap_Period, 0, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX); // read a block with no sync & no manchester - will be all '0' if not modulating RFIDlerConfig.Manchester= FALSE; if(read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, RFIDlerConfig.DataBits, RFIDlerConfig.Sync, 0, RFIDlerConfig.Timeout, NO_ONESHOT_READ, HEX) == RFIDlerConfig.DataBits) { if(strcmp(tmp, "0000000000000000") != 0) blank= FALSE; RFIDlerConfig.Manchester= TRUE; if(blank && get_tag_uid(tmp) && q5_read_block(tmp, 0)) { UserMessageNum("\r\nFound tag with gap %d", gap); UserMessageNum(" one %d", one); UserMessageNum(" zero %d", zero); found= TRUE; } } } UserMessage("%s", "\r\n"); return found; }
BOOL hitag2_config_block_show(BYTE *config, BYTE *password, BYTE *key) { BYTE value= hextobyte(config); // first byte only used as config UserMessage(" PWD Block (1): %.8s ", password); printhexreadable(password, 4); UserMessage("\r\n\r\n Key Block (2): %.8s ", key); printhexreadable(key, 4); UserMessage("\r\n\r\n Config Block (3): %.8s\r\n\r\n", config); UserMessageNum(" Page 1 & 2: %d = ", GET_CONFIG(value, HITAG2_MASK_PAGE_1_2_OTP_PROTECT, HITAG2_SHIFT_PAGE_1_2_OTP_PROTECT)); if(GET_CONFIG(value, HITAG2_MASK_SECURITY, HITAG2_SHIFT_SECURITY)) UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_1_2_OTP_PROTECT, HITAG2_SHIFT_PAGE_1_2_OTP_PROTECT) ? "No Read / No Write" : "Read / Write"); else UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_1_2_OTP_PROTECT, HITAG2_SHIFT_PAGE_1_2_OTP_PROTECT) ? "Page 1: No Read / No Write, Page 2: Read Only" : "Read / Write"); UserMessageNum(" Page 3: %d = ", GET_CONFIG(value, HITAG2_MASK_PAGE_3_OTP_PROTECT, HITAG2_SHIFT_PAGE_3_OTP_PROTECT)); UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_3_OTP_PROTECT, HITAG2_SHIFT_PAGE_3_OTP_PROTECT) ? "Read Only" : "Read / Write"); UserMessageNum(" Page 4 & 5: %d = ", GET_CONFIG(value, HITAG2_MASK_PAGE_4_5_PROTECT, HITAG2_SHIFT_PAGE_4_5_PROTECT)); UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_4_5_PROTECT, HITAG2_SHIFT_PAGE_4_5_PROTECT) ? "Read Only" : "Read / Write"); UserMessageNum(" Page 6 & 7: %d = ", GET_CONFIG(value, HITAG2_MASK_PAGE_6_7_PROTECT, HITAG2_SHIFT_PAGE_6_7_PROTECT)); UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_6_7_PROTECT, HITAG2_SHIFT_PAGE_6_7_PROTECT) ? "Read Only" : "Read / Write"); UserMessageNum(" Security: %d = ", GET_CONFIG(value, HITAG2_MASK_SECURITY, HITAG2_SHIFT_SECURITY)); UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_SECURITY, HITAG2_SHIFT_SECURITY) ? "Crypto" : "Password"); UserMessageNum(" Mode: %d = ", GET_CONFIG(value, HITAG2_MASK_MODE, HITAG2_SHIFT_MODE)); UserMessage("%s\r\n", (BYTE *) Hitag2_Modes[GET_CONFIG(value, HITAG2_MASK_MODE, HITAG2_SHIFT_MODE)]); UserMessageNum(" Modulation: %d = ", GET_CONFIG(value, HITAG2_MASK_MODULATION, HITAG2_SHIFT_MODULATION)); UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_MODULATION, HITAG2_SHIFT_MODULATION) ? "BiPhase" : "Manchester"); UserMessage("\r\n PWD Block (3): %.6s ", config + 2); printhexreadable(config + 2, 3); UserMessage("%s", "\r\n"); return TRUE; }
// decode externally sniffed PWM BOOL hitag2_decode_pwm(unsigned long pulses[], unsigned long gaps[], unsigned int count) { unsigned int i, j; BOOL decoded= FALSE, encrypted= FALSE, auth= FALSE; BYTE out[65], tmp[33], x; // max response from hitag2 is 64 bits j= 0; while(j < count) { i= generic_decode_pwm(out, &pulses[j], 10, 256, &gaps[j], 10, 80, count - j); if(i) { // there are only 4 message sizes, so decode accordingly switch(strlen(out)) { // start_auth case 5: auth= FALSE; if(memcmp(out, HITAG2_START_AUTH, 5) == 0) { UserMessage("\r\n%s, START_AUTH", out); auth= TRUE; } else UserMessage("\r\n%s, ?INVALID?", out); encrypted= FALSE; break; // read/write/halt case 10: auth= FALSE; if(encrypted) { UserMessage("\r\n%s, CMD_ENCRYPTED", out); break; } if(memcmp(out, HITAG2_HALT, 2) == 0) { UserMessage("\r\n%s, HALT", out); break; } if(memcmp(out, HITAG2_READ_PAGE, 2) == 0) UserMessage("\r\n%s, READ_PAGE:", out); if(memcmp(out, HITAG2_READ_PAGE_INVERTED, 2) == 0) UserMessage("\r\n%s, READ_PAGE_INVERTED:", out); if(memcmp(out, HITAG2_WRITE_PAGE, 2) == 0) UserMessage("\r\n%s, WRITE_PAGE:", out); binstringtobyte(&x, &out[2], 3); UserMessageNum("%d", x); break; // password or data case 32: if(auth) UserMessage("\r\n%s, PWD:", out); else UserMessage("\r\n%s, DATA:", out); binstringtohex(out, out); UserMessage("%s", out); auth= FALSE; break; // crypto handshake case 64: UserMessage("\r\n%s, PRN:", out); memcpy(tmp, out, 32); tmp[32]= '\0'; binstringtohex(out, tmp); UserMessage("%s: SECRET:", out); binstringtohex(out, out + 32); UserMessage("%s", out); encrypted= TRUE; auth= FALSE; break; default: UserMessage("\r\n%s,?INVALID?", out); } decoded= TRUE; j += i; } else break; } UserMessage("%s", "\r\n"); return decoded; }
// decode externally sniffed PWM BOOL hitag1_decode_pwm(unsigned long pulses[], unsigned long gaps[], unsigned int count) { unsigned int i, j; BOOL decoded= FALSE; BYTE out[46], tmp[9], x; // max command from hitag1 is 5 bit command plus 32 bits + 8 bit crc == 45 j= 0; while(j < count) { i= generic_decode_pwm(out, &pulses[j], 10, 256, &gaps[j], 10, 80, count - j); if(i) { // there are only 5 message sizes, so decode accordingly switch(strlen(out)) { // halt case 4: if(memcmp(out, HITAG1_HALT, 4) == 0) UserMessage("\r\n%s, HALT", out); else UserMessage("\r\n%s, ?INVALID?", out); break; // get UID case 5: if(memcmp(out, HITAG1_SET_CC, 5) == 0) UserMessage("\r\n%s, SET_CC", out); else UserMessage("\r\n%s, ?INVALID?", out); break; // read/write case 20: if(memcmp(out, HITAG1_RDPPAGE, 4) == 0) UserMessage("\r\n%s, READ_PLAINTEXT_PAGE:", out); else if(memcmp(out, HITAG1_WRPPAGE, 4) == 0) UserMessage("\r\n%s, WRITE_PLAINTEXT_PAGE:", out); else { UserMessage("\r\n%s, ?INVALID?", out); break; } out[20]= '\0'; binstringtohex(tmp, out + 4); // page UserMessage("%.2s:", tmp); // crc UserMessage("%s", tmp + 2); break; // data case 40: UserMessage("\r\n%s, DATA:", out); out[40]= '\0'; binstringtohex(tmp, out); // DATA UserMessage("%.8s:", tmp); // CRC UserMessage("%s", tmp + 8); break; // select case 45: if(memcmp(out, HITAG1_SELECT, 5) == 0) { UserMessage("\r\n%s, SELECT:", out); out[45]= '\0'; binstringtohex(tmp, out + 5); // UID UserMessage("%.8s:", tmp); // CRC UserMessage("%s", tmp + 8); } else UserMessage("\r\n%s, ?INVALID?", out); break; default: UserMessage("\r\n%s,?INVALID?", out); } decoded= TRUE; j += i; } else break; } UserMessage("%s", "\r\n"); return decoded; }
BOOL vtag_write_to_tag(BYTE *pass) { unsigned int block, config_block_no; BYTE tmp[MAXBLOCKSIZE + 1]; BOOL auth= FALSE; StoredConfig tmptag; // preserve tag type memcpy(&tmptag, &RFIDlerConfig, sizeof(RFIDlerConfig)); // set real tag to vtag type if not already the same if(RFIDlerConfig.TagType != RFIDlerVTag.TagType) if(!tag_set(RFIDlerVTag.TagType)) { memcpy(&RFIDlerConfig, &tmptag, sizeof(RFIDlerConfig)); return FALSE; } // reset target tag, but don't care if we get UID as it may not be in a valid mode get_tag_uid(tmp); // re-auth if(!tag_login(block, tmp, pass)) tag_auth(block, tmp, pass); // initialise target in default mode // get config block number if(!config_block_number(&config_block_no, RFIDlerConfig.TagType)) return FALSE; // get default config block data tmp[HEXDIGITS(RFIDlerVTag.BlockSize)]= '\0'; if (!config_block(tmp, RFIDlerConfig.TagType, RFIDlerConfig.TagType)) { memcpy(&RFIDlerConfig, &tmptag, sizeof(RFIDlerConfig)); return FALSE; } // write default config if(!write_tag(config_block_no, tmp, VERIFY)) { memcpy(&RFIDlerConfig, &tmptag, sizeof(RFIDlerConfig)); return FALSE; } // reset tag again get_tag_uid(tmp); // write all VTAG blocks with valid data in them // but avoid writing config block until last as tag may stop responding tmp[HEXDIGITS(RFIDlerVTag.BlockSize)]= '\0'; for(block= 0 ; block < RFIDlerVTag.DataBlocks ; ++block) if(block != config_block_no && RFIDlerVTag.Data[HEXDIGITS(RFIDlerVTag.BlockSize * block)]) { // try to login/auth in case target tag requires it // don't care if we fail if(!(auth= tag_login(block, tmp, pass))) auth= tag_auth(block, tmp, pass); memcpy(tmp, &RFIDlerVTag.Data[HEXDIGITS(RFIDlerVTag.BlockSize * block)], HEXDIGITS(RFIDlerVTag.BlockSize)); UserMessageNum("\r\n%d: ", block); UserMessage("%s", tmp); // failure allowed as we may be trying to write locked blocks if(!write_tag(block, tmp, VERIFY)) { UserMessage("%s", " Failed!"); if(!auth) UserMessage("%s", " (Auth/Login)"); } } // write config block (no verify as some tags stop talking after config change) if(!tag_login(block, tmp, pass)) tag_auth(block, tmp, pass); tmp[HEXDIGITS(RFIDlerVTag.BlockSize)]= '\0'; memcpy(tmp, &RFIDlerVTag.Data[HEXDIGITS(RFIDlerVTag.BlockSize * config_block_no)], HEXDIGITS(RFIDlerVTag.BlockSize)); UserMessageNum("\r\n\r\n%d: ", config_block_no); UserMessage("%s", tmp); if(!write_tag(config_block_no, tmp, NO_VERIFY)) { memcpy(&RFIDlerConfig, &tmptag, sizeof(RFIDlerConfig)); return FALSE; } memcpy(&RFIDlerConfig, &tmptag, sizeof(RFIDlerConfig)); return TRUE; }