whitespace

This commit is contained in:
iceman1001 2020-03-10 17:11:57 +01:00
commit 57788d5751
4 changed files with 230 additions and 321 deletions

View file

@ -408,7 +408,7 @@ void fix_ac_decoding(uint8_t *input, size_t len) {
*/ */
// looks at number of received bits. // looks at number of received bits.
// 0 = collision? // 0 = collision?
// 32 = good response // 32 = good response
bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) { bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) {
@ -582,15 +582,15 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t
Dbhexdump(4, logdata_1, false); Dbhexdump(4, logdata_1, false);
bSuccessful = true; bSuccessful = true;
return false; return false;
/* /*
// read next page of card until done // read next page of card until done
tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE
tx[1] = blocknr << 4; tx[1] = blocknr << 4;
crc = hitag_crc(tx, 12); crc = hitag_crc(tx, 12);
tx[1] |= crc >> 4; tx[1] |= crc >> 4;
tx[2] = crc << 4; tx[2] = crc << 4;
*txlen = 20; *txlen = 20;
*/ */
} }
} }
break; break;
@ -1091,7 +1091,7 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
uint32_t block = 0; uint32_t block = 0;
for (size_t i = 0; i < 12; i++) { for (size_t i = 0; i < 12; i++) {
// num2bytes? // num2bytes?
for (size_t j = 0; j < 4; j++) { for (size_t j = 0; j < 4; j++) {
block <<= 8; block <<= 8;
block |= tag.sectors[i][j]; block |= tag.sectors[i][j];
@ -1105,30 +1105,30 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
size_t nrzs = 0, periods = 0; size_t nrzs = 0, periods = 0;
// uint32_t command_start = 0, command_duration = 0; // uint32_t command_start = 0, command_duration = 0;
// int16_t checked = 0; // int16_t checked = 0;
// SIMULATE // SIMULATE
while (!BUTTON_PRESS()) { while (!BUTTON_PRESS()) {
LED_D_ON(); LED_D_ON();
// lf_reset_counter(); // lf_reset_counter();
LED_A_OFF(); LED_A_OFF();
WDT_HIT(); WDT_HIT();
/* /*
// only every 1000th times, in order to save time when collecting samples. // only every 1000th times, in order to save time when collecting samples.
if (checked == 100) { if (checked == 100) {
if (data_available()) { if (data_available()) {
checked = -1; checked = -1;
break; break;
} else { } else {
checked = 0; checked = 0;
} }
} }
++checked; ++checked;
*/ */
rxlen = 0; rxlen = 0;
@ -1220,8 +1220,8 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
if (nrzs < 5) { if (nrzs < 5) {
Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs);
continue; continue;
} else { } else {
for (size_t i = 0; i < 5; i++){ for (size_t i = 0; i < 5; i++) {
if (nrz_samples[i] != 1) { if (nrz_samples[i] != 1) {
Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one", i); Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one", i);
} }
@ -1229,7 +1229,7 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
} }
// Pack the response into a byte array // Pack the response into a byte array
for (size_t i = 5; i < 37; i++){ for (size_t i = 5; i < 37; i++) {
uint8_t bit = nrz_samples[i]; uint8_t bit = nrz_samples[i];
rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); rx[rxlen / 8] |= bit << (7 - (rxlen % 8));
rxlen++; rxlen++;
@ -1401,7 +1401,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
// hitagS settings // hitagS settings
t_wait_1 = 204; t_wait_1 = 204;
t_wait_2 = 128; t_wait_2 = 128;
/*tag_size = 256;*/
flipped_bit = 0; flipped_bit = 0;
tag_size = 8; tag_size = 8;
DBG DbpString("Configured for hitagS reader"); DBG DbpString("Configured for hitagS reader");
@ -1657,7 +1656,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
uint32_t command_start = 0; uint32_t command_start = 0;
uint32_t command_duration = 0; uint32_t command_duration = 0;
uint32_t response_start = 0; uint32_t response_start = 0;
uint32_t response_duration = 0; uint32_t response_duration = 0;
uint8_t rx[HITAG_FRAME_LEN]; uint8_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0; size_t rxlen = 0;
uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t txbuf[HITAG_FRAME_LEN];
@ -1731,14 +1730,14 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
tag_size = 8; tag_size = 8;
DbpString("Configured for hitagS writer"); DbpString("Configured for hitagS writer");
} else if (htf < 20) { } else if (htf < 20) {
// hitag1 settings // hitag1 settings
t_wait_1 = 204; t_wait_1 = 204;
t_wait_2 = 128; t_wait_2 = 128;
tag_size = 256; tag_size = 256;
flipped_bit = 0; flipped_bit = 0;
DbpString("Configured for hitag1 writer"); DbpString("Configured for hitag1 writer");
} else if (htf < 30) { } else if (htf < 30) {
// hitag2 settings // hitag2 settings
t_wait_1 = HITAG_T_WAIT_1_MIN; t_wait_1 = HITAG_T_WAIT_1_MIN;
t_wait_2 = HITAG_T_WAIT_2_MIN; t_wait_2 = HITAG_T_WAIT_2_MIN;
tag_size = 48; tag_size = 48;
@ -1783,7 +1782,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
} }
} }
// Wait for t_wait_2 carrier periods after the last tag bit before transmitting, // Wait for t_wait_2 carrier periods after the last tag bit before transmitting,
lf_wait_periods(t_wait_2); lf_wait_periods(t_wait_2);
command_start += t_wait_2; command_start += t_wait_2;

View file

@ -38,70 +38,60 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
uint8_t temp[20]; uint8_t temp[20];
int i; int i;
uint8_t *spaceptr = NULL; uint8_t *spaceptr = NULL;
// get uid as hexstring // get uid as hexstring
if(!hitag2_get_uid(uidhex)) if (!hitag2_get_uid(uidhex)) {
{
UserMessage("Cannot get UID\r\n"); UserMessage("Cannot get UID\r\n");
return false; return false;
} }
// convert uid hexstring to binarray // convert uid hexstring to binarray
hextobinarray(uid, uidhex); hextobinarray(uid, uidhex);
// convert nR and aR hexstrings to binarray // convert nR and aR hexstrings to binarray
spaceptr = strchr(nrarhex, ' '); spaceptr = strchr(nrarhex, ' ');
if (!spaceptr) if (!spaceptr) {
{
UserMessage("Please supply a valid nR aR pair\r\n"); UserMessage("Please supply a valid nR aR pair\r\n");
return false; return false;
} }
*spaceptr = 0x00; *spaceptr = 0x00;
if (hextobinarray(nrar, nrarhex) != 32) if (hextobinarray(nrar, nrarhex) != 32) {
{
UserMessage("nR is not 32 bits long\r\n"); UserMessage("nR is not 32 bits long\r\n");
return false; return false;
} }
if (hextobinarray(nrar + 32, spaceptr + 1) != 32) if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
{
UserMessage("aR is not 32 bits long\r\n"); UserMessage("aR is not 32 bits long\r\n");
return false; return false;
} }
// find a valid encrypted command // find a valid encrypted command
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
{
UserMessage("Cannot find a valid encrypted command\r\n"); UserMessage("Cannot find a valid encrypted command\r\n");
return false; return false;
} }
// find the 'read page 0' command and recover key stream // find the 'read page 0' command and recover key stream
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
{
UserMessage("Cannot find encrypted 'read page0' command\r\n"); UserMessage("Cannot find encrypted 'read page0' command\r\n");
return false; return false;
} }
// empty the response string // empty the response string
response[0] = 0x00; response[0] = 0x00;
// read all pages using key stream // read all pages using key stream
for (i=0; i<8; i++) for (i = 0; i < 8; i++) {
{ if (hitag2crack_read_page(pagehex, i, nrar, keybits)) {
if (hitag2crack_read_page(pagehex, i, nrar, keybits))
{
sprintf(temp, "%1d: %s\r\n", i, pagehex); sprintf(temp, "%1d: %s\r\n", i, pagehex);
} } else {
else
{
sprintf(temp, "%1d:\r\n", i); sprintf(temp, "%1d:\r\n", i);
} }
// add page string to response // add page string to response
strcat(response, temp); strcat(response, temp);
} }
return true; return true;
} }
@ -113,16 +103,16 @@ bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) { bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) {
uint8_t guess[10]; uint8_t guess[10];
uint8_t responsestr[9]; uint8_t responsestr[9];
// UserMessage("Finding valid encrypted command:"); // UserMessage("Finding valid encrypted command:");
// we're going to hold bits 5, 7, 8 and 9 and brute force the rest // we're going to hold bits 5, 7, 8 and 9 and brute force the rest
// e.g. x x x x x 0 x 0 0 0 // e.g. x x x x x 0 x 0 0 0
for (uint8_t a=0; a<2; a++) { for (uint8_t a = 0; a < 2; a++) {
for (uint8_t b=0; b<2; b++) { for (uint8_t b = 0; b < 2; b++) {
for (uint8_t c=0; c<2; c++) { for (uint8_t c = 0; c < 2; c++) {
for (uint8_t d=0; d<2; d++) { for (uint8_t d = 0; d < 2; d++) {
for (uint8_t e=0; e<2; e++) { for (uint8_t e = 0; e < 2; e++) {
for (uint8_t g=0; g<2; g++) { for (uint8_t g = 0; g < 2; g++) {
// build binarray // build binarray
guess[0] = a; guess[0] = a;
guess[1] = b; guess[1] = b;
@ -175,65 +165,50 @@ bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8
UserMessage("Finding 'read page 0' command:"); UserMessage("Finding 'read page 0' command:");
// we're going to brute the missing 4 bits of the valid encrypted command // we're going to brute the missing 4 bits of the valid encrypted command
for (a=0; a<2; a++) for (a = 0; a < 2; a++) {
{ for (b = 0; b < 2; b++) {
for (b=0; b<2; b++) for (c = 0; c < 2; c++) {
{ for (d = 0; d < 2; d++) {
for (c=0; c<2; c++)
{
for (d=0; d<2; d++)
{
// create our guess by bit flipping the pattern of bits // create our guess by bit flipping the pattern of bits
// representing the inverted bit and the 3 page bits // representing the inverted bit and the 3 page bits
// in both the non-inverted and inverted parts of the // in both the non-inverted and inverted parts of the
// encrypted command. // encrypted command.
memcpy(guess, e_firstcmd, 10); memcpy(guess, e_firstcmd, 10);
if (a) if (a) {
{
guess[5] = !guess[5]; guess[5] = !guess[5];
guess[0] = !guess[0]; guess[0] = !guess[0];
} }
if (b) if (b) {
{
guess[7] = !guess[7]; guess[7] = !guess[7];
guess[2] = !guess[2]; guess[2] = !guess[2];
} }
if (c) if (c) {
{
guess[8] = !guess[8]; guess[8] = !guess[8];
guess[3] = !guess[3]; guess[3] = !guess[3];
} }
if (d) if (d) {
{
guess[9] = !guess[9]; guess[9] = !guess[9];
guess[4] = !guess[4]; guess[4] = !guess[4];
} }
// try the guess // try the guess
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
{
// check if it was valid // check if it was valid
if (strcmp(responsestr, ERROR_RESPONSE) != 0) if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
{
// convert response to binarray // convert response to binarray
hextobinarray(e_uid, responsestr); hextobinarray(e_uid, responsestr);
// test if the guess was 'read page 0' command // test if the guess was 'read page 0' command
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
{
return true; return true;
} }
} } else {
else
{
#ifdef RFIDLER_DEBUG #ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
#endif #endif
} }
} } else {
else #ifdef RFIDLER_DEBUG
{
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
#endif #endif
} }
@ -262,56 +237,51 @@ bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, u
uint8_t e_ext_cmd[40]; uint8_t e_ext_cmd[40];
uint8_t responsestr[9]; uint8_t responsestr[9];
int i; int i;
// copy encrypted cmd to cipherbits // copy encrypted cmd to cipherbits
memcpy(cipherbits, e_cmd, 10); memcpy(cipherbits, e_cmd, 10);
// copy encrypted uid to cipherbits // copy encrypted uid to cipherbits
memcpy(cipherbits + 10, e_uid, 32); memcpy(cipherbits + 10, e_uid, 32);
// copy cmd to plainbits // copy cmd to plainbits
binstringtobinarray(plainbits, READP0CMD); binstringtobinarray(plainbits, READP0CMD);
// copy uid to plainbits // copy uid to plainbits
memcpy(plainbits + 10, uid, 32); memcpy(plainbits + 10, uid, 32);
// xor the plainbits with the cipherbits to get keybits // xor the plainbits with the cipherbits to get keybits
hitag2crack_xor(keybits, plainbits, cipherbits, 42); hitag2crack_xor(keybits, plainbits, cipherbits, 42);
// create extended cmd -> 4 * READP0CMD = 40 bits // create extended cmd -> 4 * READP0CMD = 40 bits
for (i=0; i<4; i++) for (i = 0; i < 4; i++) {
{
binstringtobinarray(ext_cmd + (i * 10), READP0CMD); binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
} }
// xor extended cmd with keybits // xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40); hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40);
// send extended encrypted cmd // send extended encrypted cmd
if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) {
{
// test if it was valid // test if it was valid
if (strcmp(responsestr, ERROR_RESPONSE) != 0) if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
{
return true; return true;
} }
} } else {
else
{
#ifdef RFIDLER_DEBUG #ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
#endif #endif
} }
return false; return false;
} }
// hitag2crack_xor XORs the source with the pad to produce the target. // hitag2crack_xor XORs the source with the pad to produce the target.
// source, target and pad are binarrays of length len. // source, target and pad are binarrays of length len.
void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) { void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) {
for (int i=0; i<len; i++) { for (int i = 0; i < len; i++) {
target[i] = source[i] ^ pad[i]; target[i] = source[i] ^ pad[i];
} }
} }
@ -329,40 +299,34 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar,
uint8_t e_response[32]; uint8_t e_response[32];
uint8_t response[32]; uint8_t response[32];
int i; int i;
if ((pagenum < 0) || (pagenum > 7)) if ((pagenum < 0) || (pagenum > 7)) {
{
UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n"); UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
return false; return false;
} }
// create cmd // create cmd
binstringtobinarray(cmd, READP0CMD); binstringtobinarray(cmd, READP0CMD);
if (pagenum & 0x1) if (pagenum & 0x1) {
{
cmd[9] = !cmd[9]; cmd[9] = !cmd[9];
cmd[4] = !cmd[4]; cmd[4] = !cmd[4];
} }
if (pagenum & 0x2) if (pagenum & 0x2) {
{
cmd[8] = !cmd[8]; cmd[8] = !cmd[8];
cmd[3] = !cmd[3]; cmd[3] = !cmd[3];
} }
if (pagenum & 0x4) if (pagenum & 0x4) {
{
cmd[7] = !cmd[7]; cmd[7] = !cmd[7];
cmd[2] = !cmd[2]; cmd[2] = !cmd[2];
} }
// encrypt command // encrypt command
hitag2crack_xor(e_cmd, cmd, keybits, 10); hitag2crack_xor(e_cmd, cmd, keybits, 10);
// send encrypted command // send encrypted command
if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) {
{
// check if it is valid // check if it is valid
if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) {
{
// convert to binarray // convert to binarray
hextobinarray(e_response, e_responsestr); hextobinarray(e_response, e_responsestr);
// decrypt response // decrypt response
@ -370,17 +334,13 @@ bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar,
// convert to hexstring // convert to hexstring
binarraytohex(responsestr, response, 32); binarraytohex(responsestr, response, 32);
return true; return true;
} } else {
else
{
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
} }
} } else {
else
{
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n"); UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
} }
return false; return false;
} }
@ -397,8 +357,7 @@ bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, i
int ret = 0; int ret = 0;
// get the UID // get the UID
if(!hitag2_get_uid(uid)) if (!hitag2_get_uid(uid)) {
{
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n"); UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
return false; return false;
} }
@ -407,22 +366,19 @@ bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, i
CryptoActive = false; CryptoActive = false;
// get the UID again // get the UID again
if(!hitag2_get_uid(uid)) if (!hitag2_get_uid(uid)) {
{
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n"); UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
return false; return false;
} }
// send nrar and receive (useless) encrypted page 3 value // send nrar and receive (useless) encrypted page 3 value
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
{
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n"); UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n");
return false; return false;
} }
// send encrypted command // send encrypted command
if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) {
{
#ifdef RFIDLER_DEBUG #ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n"); UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
#endif #endif
@ -442,34 +398,29 @@ bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, b
int ret = 0; int ret = 0;
// START_AUTH kills active crypto session // START_AUTH kills active crypto session
CryptoActive= false; CryptoActive = false;
if(!rwd_send(msg, len, reset, BLOCK, state, 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)) if (!rwd_send(msg, len, reset, BLOCK, state, 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)) {
{
UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n"); UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n");
return false; return false;
} }
// skip 1/2 bit to synchronise manchester // skip 1/2 bit to synchronise manchester
HW_Skip_Bits = 1; HW_Skip_Bits = 1;
ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY); ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY);
// check if response was a valid length (5 sync bits + 32 bits response) // check if response was a valid length (5 sync bits + 32 bits response)
if (ret == 37) if (ret == 37) {
{
// check sync bits // check sync bits
if (memcmp(tmp, Hitag2Sync, 5) != 0) if (memcmp(tmp, Hitag2Sync, 5) != 0) {
{
UserMessage("hitag2crack_tx_rx: no sync\r\n"); UserMessage("hitag2crack_tx_rx: no sync\r\n");
return false; return false;
} }
// convert response to hexstring // convert response to hexstring
binarraytohex(responsestr, tmp + 5, 32); binarraytohex(responsestr, tmp + 5, 32);
return true; return true;
} } else {
else
{
#ifdef RFIDLER_DEBUG #ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_tx_rx: wrong rx len\r\n"); UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
#endif #endif
@ -485,58 +436,53 @@ bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) {
uint32_t initvector; uint32_t initvector;
uint8_t *spaceptr; uint8_t *spaceptr;
uint8_t *dataptr; uint8_t *dataptr;
// extract vals from input // extract vals from input
dataptr = input; dataptr = input;
spaceptr = strchr(dataptr, ' '); spaceptr = strchr(dataptr, ' ');
if (!spaceptr) if (!spaceptr) {
{
UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n"); UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
return false; return false;
} }
*spaceptr = 0x00; *spaceptr = 0x00;
if (strlen(dataptr) != 12) if (strlen(dataptr) != 12) {
{
UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n"); UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
return false; return false;
} }
sharedkey = rev64(hexreversetoulonglong(dataptr)); sharedkey = rev64(hexreversetoulonglong(dataptr));
dataptr = spaceptr+1; dataptr = spaceptr + 1;
spaceptr = strchr(dataptr, ' '); spaceptr = strchr(dataptr, ' ');
if (!spaceptr) if (!spaceptr) {
{
UserMessage("/r/nno UID\r\n"); UserMessage("/r/nno UID\r\n");
return false; return false;
} }
*spaceptr = 0x00; *spaceptr = 0x00;
if (strlen(dataptr) != 8) if (strlen(dataptr) != 8) {
{
UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n"); UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
return false; return false;
} }
serialnum = rev32(hexreversetoulong(dataptr)); serialnum = rev32(hexreversetoulong(dataptr));
dataptr = spaceptr+1; dataptr = spaceptr + 1;
if (strlen(dataptr) != 8) if (strlen(dataptr) != 8) {
{
UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n"); UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n");
return false; return false;
} }
initvector = rev32(hexreversetoulong(dataptr)); initvector = rev32(hexreversetoulong(dataptr));
// start up crypto engine // start up crypto engine
hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector); hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector);
strcpy(response, "Success\r\n"); strcpy(response, "Success\r\n");
return true; return true;
} }
@ -545,21 +491,20 @@ bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) {
uint8_t binhex[9]; uint8_t binhex[9];
uint8_t binstr[33]; uint8_t binstr[33];
uint32_t binulong; uint32_t binulong;
if (strlen(hex) != 8) if (strlen(hex) != 8) {
{
UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n"); UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
return false; return false;
} }
binulong = hextoulong(hex); binulong = hextoulong(hex);
ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32); ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32);
binarraytobinstring(binstr, bin, 32); binarraytobinstring(binstr, bin, 32);
binarraytohex(binhex, bin, 32); binarraytohex(binhex, bin, 32);
// UserMessage("ar = %s\r\n", binstr); // UserMessage("ar = %s\r\n", binstr);
// UserMessage("arhex = %s\r\n", binhex); // UserMessage("arhex = %s\r\n", binhex);
strcpy(response, binhex); strcpy(response, binhex);
return true; return true;
} }
@ -570,17 +515,16 @@ bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) {
uint8_t binstr[33]; uint8_t binstr[33];
uint32_t binulong; uint32_t binulong;
int len; int len;
len = strlen(e_binstr); len = strlen(e_binstr);
if (len > 32) if (len > 32) {
{
UserMessage("\r\nbinary string must be <= 32 bits\r\n"); UserMessage("\r\nbinary string must be <= 32 bits\r\n");
return false; return false;
} }
binstringtobinarray(e_bin, e_binstr); binstringtobinarray(e_bin, e_binstr);
binulong = binarraytoulong(e_bin, len); binulong = binarraytoulong(e_bin, len);
ulongtobinarray(bin, hitag2_crypt(binulong, len), len); ulongtobinarray(bin, hitag2_crypt(binulong, len), len);
binarraytobinstring(binstr, bin, len); binarraytobinstring(binstr, bin, len);
strcpy(response, binstr); strcpy(response, binstr);
@ -595,7 +539,7 @@ bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) {
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) { bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) {
return hitag2crack_decrypt_bin(response, e_binstr); return hitag2crack_decrypt_bin(response, e_binstr);
} }
// hitag2_keystream uses the first crack algorithm described in the paper, // hitag2_keystream uses the first crack algorithm described in the paper,
// Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits // Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits
// of keystream. // of keystream.
@ -618,102 +562,90 @@ bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) {
int i; int i;
uint8_t *spaceptr = NULL; uint8_t *spaceptr = NULL;
/* /*
keybits = malloc(2080); keybits = malloc(2080);
if (!keybits) { if (!keybits) {
UserMessage("cannot malloc keybits\r\n"); UserMessage("cannot malloc keybits\r\n");
return false; return false;
} }
*/ */
// get uid as hexstring // get uid as hexstring
if(!hitag2_get_uid(uidhex)) if (!hitag2_get_uid(uidhex)) {
{
UserMessage("Cannot get UID\r\n"); UserMessage("Cannot get UID\r\n");
return false; return false;
} }
// convert uid hexstring to binarray // convert uid hexstring to binarray
hextobinarray(uid, uidhex); hextobinarray(uid, uidhex);
// convert nR and aR hexstrings to binarray // convert nR and aR hexstrings to binarray
spaceptr = strchr(nrarhex, ' '); spaceptr = strchr(nrarhex, ' ');
if (!spaceptr) if (!spaceptr) {
{
UserMessage("Please supply a valid nR aR pair\r\n"); UserMessage("Please supply a valid nR aR pair\r\n");
return false; return false;
} }
*spaceptr = 0x00; *spaceptr = 0x00;
if (hextobinarray(nrar, nrarhex) != 32) if (hextobinarray(nrar, nrarhex) != 32) {
{
UserMessage("nR is not 32 bits long\r\n"); UserMessage("nR is not 32 bits long\r\n");
return false; return false;
} }
if (hextobinarray(nrar + 32, spaceptr + 1) != 32) if (hextobinarray(nrar + 32, spaceptr + 1) != 32) {
{
UserMessage("aR is not 32 bits long\r\n"); UserMessage("aR is not 32 bits long\r\n");
return false; return false;
} }
// find a valid encrypted command // find a valid encrypted command
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) {
{
UserMessage("Cannot find a valid encrypted command\r\n"); UserMessage("Cannot find a valid encrypted command\r\n");
return false; return false;
} }
// find the 'read page 0' command and recover key stream // find the 'read page 0' command and recover key stream
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) {
{
UserMessage("Cannot find encrypted 'read page0' command\r\n"); UserMessage("Cannot find encrypted 'read page0' command\r\n");
return false; return false;
} }
// using the 40 bits of keystream in keybits, sending commands with ever // using the 40 bits of keystream in keybits, sending commands with ever
// increasing lengths to acquire 2048 bits of key stream. // increasing lengths to acquire 2048 bits of key stream.
kslen = 40; kslen = 40;
while (kslen < 2048) while (kslen < 2048) {
{
ksoffset = 0; ksoffset = 0;
if (!hitag2crack_send_auth(nrar)) if (!hitag2crack_send_auth(nrar)) {
{
UserMessage("hitag2crack_send_auth failed\r\n"); UserMessage("hitag2crack_send_auth failed\r\n");
return false; return false;
} }
// while we have at least 52 bits of keystream, consume it with // while we have at least 52 bits of keystream, consume it with
// extended read page 0 commands. 52 = 10 (min command len) + // extended read page 0 commands. 52 = 10 (min command len) +
// 32 (response) + 10 (min command len we'll send) // 32 (response) + 10 (min command len we'll send)
while ((kslen - ksoffset) >= 52) while ((kslen - ksoffset) >= 52) {
{
// consume the keystream, updating ksoffset as we go // consume the keystream, updating ksoffset as we go
if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) {
{
UserMessage("hitag2crack_consume_keystream failed\r\n"); UserMessage("hitag2crack_consume_keystream failed\r\n");
return false; return false;
} }
} }
// send an extended command to retrieve more keystream, updating kslen // send an extended command to retrieve more keystream, updating kslen
// as we go // as we go
if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) {
{
UserMessage("hitag2crack_extend_keystream failed\r\n"); UserMessage("hitag2crack_extend_keystream failed\r\n");
return false; return false;
} }
UserMessage("Recovered %d bits of keystream\r\n", kslen); UserMessage("Recovered %d bits of keystream\r\n", kslen);
} }
for (i=0; i<2048; i+=256) for (i = 0; i < 2048; i += 256) {
{
binarraytohex(keybitshex, keybits + i, 256); binarraytohex(keybitshex, keybits + i, 256);
UserMessage("%s\r\n", keybitshex); UserMessage("%s\r\n", keybitshex);
} }
response[0] = 0x00; response[0] = 0x00;
return true; return true;
} }
@ -724,8 +656,7 @@ bool hitag2crack_send_auth(uint8_t *nrar) {
uint8_t e_page3str[9]; uint8_t e_page3str[9];
// get the UID // get the UID
if(!hitag2_get_uid(uid)) if (!hitag2_get_uid(uid)) {
{
UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n"); UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
return false; return false;
} }
@ -734,15 +665,13 @@ bool hitag2crack_send_auth(uint8_t *nrar) {
CryptoActive = false; CryptoActive = false;
// get the UID again // get the UID again
if(!hitag2_get_uid(uid)) if (!hitag2_get_uid(uid)) {
{
UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n"); UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
return false; return false;
} }
// send nrar and receive (useless) encrypted page 3 value // send nrar and receive (useless) encrypted page 3 value
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) {
{
UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n"); UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n");
return false; return false;
} }
@ -767,46 +696,41 @@ bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, u
// 42 = 32 bit response + 10 bit command reserved for next command. conlen // 42 = 32 bit response + 10 bit command reserved for next command. conlen
// cannot be longer than 510 bits to fit into the small RWD buffer. // cannot be longer than 510 bits to fit into the small RWD buffer.
conlen = kslen - *ksoffset - 42; conlen = kslen - *ksoffset - 42;
if (conlen < 10) if (conlen < 10) {
{
UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n"); UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
return false; return false;
} }
// sanitise conlen // sanitise conlen
if (conlen > 510) if (conlen > 510) {
{
conlen = 510; conlen = 510;
} }
// calculate how many repeated commands to send in this extended command. // calculate how many repeated commands to send in this extended command.
numcmds = conlen / 10; numcmds = conlen / 10;
// build extended command // build extended command
for (i=0; i<numcmds; i++) for (i = 0; i < numcmds; i++) {
{
binstringtobinarray(ext_cmd + (i * 10), READP0CMD); binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
} }
// xor extended cmd with keybits // xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + *ksoffset, numcmds * 10); hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + *ksoffset, numcmds * 10);
// send encrypted command // send encrypted command
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
{
UserMessage("hitag2crack_consume_keystream:\r\n tx/rx cmd failed\r\n"); UserMessage("hitag2crack_consume_keystream:\r\n tx/rx cmd failed\r\n");
return false; return false;
} }
// test response // test response
if (strcmp(responsestr, ERROR_RESPONSE) == 0) if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
{
UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n"); UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n");
return false; return false;
} }
// dont bother decrypting the response - we already know the keybits // dont bother decrypting the response - we already know the keybits
// update ksoffset with command length and response // update ksoffset with command length and response
*ksoffset += (numcmds * 10) + 32; *ksoffset += (numcmds * 10) + 32;
} }
@ -825,36 +749,32 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
uint8_t responsestr[9]; uint8_t responsestr[9];
uint8_t e_response[32]; uint8_t e_response[32];
int i; int i;
// calc number of command iterations to send // calc number of command iterations to send
cmdlen = *kslen - ksoffset; cmdlen = *kslen - ksoffset;
if (cmdlen < 10) if (cmdlen < 10) {
{
UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n"); UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n");
return false; return false;
} }
numcmds = cmdlen / 10; numcmds = cmdlen / 10;
// build extended command // build extended command
for (i=0; i<numcmds; i++) for (i = 0; i < numcmds; i++) {
{
binstringtobinarray(ext_cmd + (i * 10), READP0CMD); binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
} }
// xor extended cmd with keybits // xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + ksoffset, numcmds * 10); hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + ksoffset, numcmds * 10);
// send extended encrypted cmd // send extended encrypted cmd
if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) {
{
UserMessage("hitag2crack_extend_keystream:\r\n tx/rx cmd failed\r\n"); UserMessage("hitag2crack_extend_keystream:\r\n tx/rx cmd failed\r\n");
return false; return false;
} }
// test response // test response
if (strcmp(responsestr, ERROR_RESPONSE) == 0) if (strcmp(responsestr, ERROR_RESPONSE) == 0) {
{
UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n"); UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n");
return false; return false;
} }
@ -867,7 +787,7 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
// update kslen // update kslen
*kslen = ksoffset + (numcmds * 10) + 32; *kslen = ksoffset + (numcmds * 10) + 32;
return true; return true;
} }
@ -875,49 +795,39 @@ bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, ui
bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) { bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) {
uint8_t tmp[9]; uint8_t tmp[9];
int i; int i;
response[0] = '\0'; response[0] = '\0';
// auth to tag // auth to tag
if (hitag2_crypto_auth(tmp, key)) if (hitag2_crypto_auth(tmp, key)) {
{
// read tag, one page at a time // read tag, one page at a time
for (i= 0; i <= 7; ++i) for (i = 0; i <= 7; ++i) {
{ if (!read_tag(tmp, i, i)) {
if(!read_tag(tmp, i, i))
{
// if read fails, it could be because of auth, // if read fails, it could be because of auth,
// so try to reauth // so try to reauth
if (!hitag2_crypto_auth(tmp, key)) if (!hitag2_crypto_auth(tmp, key)) {
{
// if we can't reauth, it's a real failure // if we can't reauth, it's a real failure
return false; return false;
} }
// temp failure (probably due to page protections) // temp failure (probably due to page protections)
strcpy(tmp, "XXXXXXXX"); strcpy(tmp, "XXXXXXXX");
} }
// page contents are in tmp // page contents are in tmp
strcat(response, tmp); strcat(response, tmp);
} }
if (interactive) if (interactive) {
{ tmp[8] = '\0';
tmp[8]= '\0'; for (i = 0; i <= 7 ; ++i) {
for(i= 0; i <= 7 ; ++i) UserMessageNum("%d: ", i);
{ memcpy(tmp, response + (i * 8), 8);
UserMessageNum("%d: ", i); UserMessage("%s\r\n", tmp);
memcpy(tmp, response + (i * 8), 8);
UserMessage("%s\r\n", tmp);
}
UserMessage("%s", "\r\n");
} }
else UserMessage("%s", "\r\n");
{ } else {
hitag2_nvm_store_tag(response); hitag2_nvm_store_tag(response);
} }
return true; return true;
} } else {
else
{
return false; return false;
} }
} }

View file

@ -1952,11 +1952,11 @@ void check_challenges(bool file_given, uint8_t *data) {
u1++; u1++;
} else if (STATE == 2 && rxlen >= 44) { } else if (STATE == 2 && rxlen >= 44) {
Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X", Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X",
unlocker[u1 - 1][0], unlocker[u1 - 1][1], unlocker[u1 - 1][0], unlocker[u1 - 1][1],
unlocker[u1 - 1][2], unlocker[u1 - 1][3], unlocker[u1 - 1][2], unlocker[u1 - 1][3],
unlocker[u1 - 1][4], unlocker[u1 - 1][5], unlocker[u1 - 1][4], unlocker[u1 - 1][5],
unlocker[u1 - 1][6], unlocker[u1 - 1][7]); unlocker[u1 - 1][6], unlocker[u1 - 1][7]);
STATE = 0; STATE = 0;
} }

View file

@ -1817,15 +1817,15 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
++check; ++check;
// test if the field exists // test if the field exists
#if defined RDV4 #if defined RDV4
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF_RDV40)) { if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF_RDV40)) {
analogCnt++; analogCnt++;
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40]; analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40];
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
if (analogCnt >= 32) { if (analogCnt >= 32) {
if ((MAX_ADC_HF_VOLTAGE_RDV40 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) { if ((MAX_ADC_HF_VOLTAGE_RDV40 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
@ -1847,13 +1847,13 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
} }
#else #else
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) { if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) {
analogCnt++; analogCnt++;
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF]; analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
if (analogCnt >= 32) { if (analogCnt >= 32) {
if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) { if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {