mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-13 01:57:25 -07:00
move hitag2 crypto parts to the common folder in order to be able to use it on the client side. Some textual and minor adaptations across the bord
This commit is contained in:
parent
cdc46d5d2b
commit
700d558432
17 changed files with 185 additions and 117 deletions
armsrc
client
common
common_arm
include
|
@ -310,6 +310,7 @@ bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, ui
|
|||
bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t timestamp_start, uint32_t timestamp_end, bool reader2tag) {
|
||||
uint8_t parity[(nbytes(bitLen) - 1) / 8 + 1];
|
||||
memset(parity, 0x00, sizeof(parity));
|
||||
// parity has amount of leftover bits.
|
||||
parity[0] = bitLen % 8;
|
||||
return LogTrace(btBytes, nbytes(bitLen), timestamp_start, timestamp_end, parity, reader2tag);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ endif
|
|||
|
||||
ifneq (,$(findstring WITH_HITAG,$(APP_CFLAGS)))
|
||||
SRC_HITAG = hitag2_crypto.c hitag2.c hitagS.c
|
||||
APP_CFLAGS += -I../common/hitag2
|
||||
else
|
||||
SRC_HITAG =
|
||||
endif
|
||||
|
|
|
@ -55,7 +55,7 @@ Public Mode B : 0x00 - 0000 0000
|
|||
Public Mode C : 0x04 - 0000 0100
|
||||
*/
|
||||
|
||||
static struct hitag2_tag tag = {
|
||||
static hitag2_t tag = {
|
||||
.state = TAG_STATE_RESET,
|
||||
.sectors = { // Password mode: | Crypto mode:
|
||||
[0] = { 0x02, 0x4e, 0x02, 0x20}, // UID | UID
|
||||
|
@ -118,6 +118,7 @@ static void hitag2_init(void) {
|
|||
#endif
|
||||
|
||||
#define HITAG_FRAME_LEN 20
|
||||
#define HITAG_FRAME_BIT_COUNT (8 * HITAG_FRAME_LEN)
|
||||
#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
|
||||
#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
|
||||
#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
|
||||
|
@ -198,7 +199,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
memcpy(rx_air, rx, nbytes(rxlen));
|
||||
|
||||
if (tag.crypto_active) {
|
||||
hitag2_cipher_transcrypt(&(tag.cs), rx, rxlen / 8, rxlen % 8);
|
||||
ht2_hitag2_cipher_transcrypt(&(tag.cs), rx, rxlen / 8, rxlen % 8);
|
||||
}
|
||||
|
||||
// Reset the transmission frame length
|
||||
|
@ -225,7 +226,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
|
||||
// Verify complement of sector index
|
||||
if (sector != ((rx[0] >> 3) & 0x07)) {
|
||||
DbpString("Transmission error (read/write)");
|
||||
DBG DbpString("Transmission error (read/write)");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -255,7 +256,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
}
|
||||
// Unknown command
|
||||
default: {
|
||||
Dbprintf("Unknown command: %02x %02x", rx[0], rx[1]);
|
||||
DBG Dbprintf("Unknown command: %02x %02x", rx[0], rx[1]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +273,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
} else {
|
||||
// Received RWD password, respond with configuration and our password
|
||||
if (memcmp(rx, tag.sectors[1], 4) != 0) {
|
||||
DbpString("Reader password is wrong");
|
||||
DBG DbpString("Reader password is wrong");
|
||||
return;
|
||||
}
|
||||
*txlen = 32;
|
||||
|
@ -290,12 +291,12 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
}
|
||||
|
||||
// Reset the cipher state
|
||||
hitag2_cipher_reset(&tag, rx);
|
||||
ht2_hitag2_cipher_reset(&tag, rx);
|
||||
|
||||
// Check if the authentication was correct
|
||||
if (!hitag2_cipher_authenticate(&(tag.cs), rx + 4)) {
|
||||
if (!ht2_hitag2_cipher_authenticate(&(tag.cs), rx + 4)) {
|
||||
// The reader failed to authenticate, do nothing
|
||||
Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!", rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
|
||||
DBG Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!", rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
|
||||
return;
|
||||
}
|
||||
// Activate encryption algorithm for all further communication
|
||||
|
@ -312,7 +313,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
// LogTraceBits(tx, txlen, 0, 0, true);
|
||||
|
||||
if (tag.crypto_active) {
|
||||
hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8);
|
||||
ht2_hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -728,13 +729,14 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
|||
*txlen = 0;
|
||||
|
||||
if (bCrypto) {
|
||||
hitag2_cipher_transcrypt(&cipher_state, rx, rxlen / 8, rxlen % 8);
|
||||
ht2_hitag2_cipher_transcrypt(&cipher_state, rx, rxlen / 8, rxlen % 8);
|
||||
}
|
||||
|
||||
if (bCrypto && !bAuthenticating && write) {
|
||||
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||
if (hitag2_write_page(rx, rxlen, tx, txlen) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Try to find out which command was send by selecting on length (in bits)
|
||||
|
@ -745,7 +747,7 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
|||
if (bCrypto) {
|
||||
// Failed during authentication
|
||||
if (bAuthenticating) {
|
||||
DbpString("Authentication failed!");
|
||||
DBG DbpString("Authentication failed!");
|
||||
return false;
|
||||
} else {
|
||||
// Failed reading a block, could be (read/write) locked, skip block and re-authenticate
|
||||
|
@ -774,16 +776,27 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
|||
// Received UID, crypto tag answer
|
||||
case 32: {
|
||||
// stage 1, got UID
|
||||
if (!bCrypto) {
|
||||
if (bCrypto == false) {
|
||||
|
||||
DBG Dbprintf("hitag2_crypto: key array ");
|
||||
DBG Dbhexdump(6, key, false);
|
||||
|
||||
uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
|
||||
|
||||
uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
|
||||
Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((REV64(ui64key)) >> 32), (uint32_t)((REV64(ui64key)) & 0xffffffff), REV32(ui32uid));
|
||||
cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0);
|
||||
// PRN
|
||||
DBG Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x"
|
||||
, (uint32_t)((REV64(ui64key)) >> 32)
|
||||
, (uint32_t)((REV64(ui64key)) & 0xffffffff)
|
||||
, REV32(ui32uid)
|
||||
);
|
||||
|
||||
cipher_state = ht2_hitag2_init(REV64(ui64key), REV32(ui32uid), 0);
|
||||
|
||||
// PRN 00 00 00 00
|
||||
memset(tx, 0x00, 4);
|
||||
// Secret data
|
||||
// Secret data FF FF FF FF
|
||||
memset(tx + 4, 0xff, 4);
|
||||
hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0);
|
||||
ht2_hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0);
|
||||
*txlen = 64;
|
||||
bCrypto = true;
|
||||
bAuthenticating = true;
|
||||
|
@ -792,7 +805,7 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
|||
if (bAuthenticating) {
|
||||
bAuthenticating = false;
|
||||
if (write) {
|
||||
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||
if (hitag2_write_page(rx, rxlen, tx, txlen) == false) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -805,7 +818,7 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
|||
blocknr++;
|
||||
}
|
||||
if (blocknr > 7) {
|
||||
DbpString("Read successful!");
|
||||
DBG DbpString("Read successful!");
|
||||
bSuccessful = true;
|
||||
return false;
|
||||
} else {
|
||||
|
@ -819,7 +832,7 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
|||
|
||||
// Unexpected response
|
||||
default: {
|
||||
Dbprintf("Unknown frame length: %d", rxlen);
|
||||
DBG Dbprintf("Unknown frame length: %d", rxlen);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -828,8 +841,8 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
|
|||
|
||||
if (bCrypto) {
|
||||
// We have to return now to avoid double encryption
|
||||
if (!bAuthenticating) {
|
||||
hitag2_cipher_transcrypt(&cipher_state, tx, *txlen / 8, *txlen % 8);
|
||||
if (bAuthenticating == false) {
|
||||
ht2_hitag2_cipher_transcrypt(&cipher_state, tx, *txlen / 8, *txlen % 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -846,7 +859,7 @@ static bool hitag2_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, si
|
|||
case 0: {
|
||||
// Stop if there is no answer while we are in crypto mode (after sending NrAr)
|
||||
if (bCrypto) {
|
||||
DbpString("Authentication failed!");
|
||||
DBG DbpString("Authentication failed!");
|
||||
return false;
|
||||
}
|
||||
*txlen = 5;
|
||||
|
@ -861,7 +874,7 @@ static bool hitag2_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, si
|
|||
memcpy(tx, NrAr, 8);
|
||||
bCrypto = true;
|
||||
} else {
|
||||
DbpString("Authentication successful!");
|
||||
DBG DbpString("Authentication successful!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -869,7 +882,7 @@ static bool hitag2_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, si
|
|||
|
||||
// Unexpected response
|
||||
default: {
|
||||
Dbprintf("Unknown frame length: %d", rxlen);
|
||||
DBG Dbprintf("Unknown frame length: %d", rxlen);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -990,7 +1003,7 @@ void EloadHitag(const uint8_t *data, uint16_t len) {
|
|||
// Tstop 36 > fc (high field stop limit)
|
||||
// Tlow 4-10 fc (reader field low time)
|
||||
void SniffHitag2(bool ledcontrol) {
|
||||
DbpString("Starting Hitag2 sniffing");
|
||||
|
||||
if (ledcontrol) LED_D_ON();
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
|
@ -1202,10 +1215,12 @@ void SniffHitag2(bool ledcontrol) {
|
|||
// }
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
response = (ra - HITAG_T_LOW);
|
||||
|
||||
} else if (ra >= HITAG_T_1_MIN) {
|
||||
// '1' bit
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
|
||||
} else if (ra >= HITAG_T_0_MIN) {
|
||||
// '0' bit
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
|
@ -1271,8 +1286,6 @@ void SniffHitag2(bool ledcontrol) {
|
|||
}
|
||||
}
|
||||
|
||||
// Reset the received frame and response timing info
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
response = 0;
|
||||
reader_frame = false;
|
||||
lastbit = 1;
|
||||
|
@ -1284,12 +1297,15 @@ void SniffHitag2(bool ledcontrol) {
|
|||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
}
|
||||
|
||||
} else {
|
||||
// Save the timer overflow, will be 0 when frame was received
|
||||
overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0);
|
||||
}
|
||||
|
||||
// Reset the frame length
|
||||
rxlen = 0;
|
||||
|
||||
// Reset the timer to restart while-loop that receives frames
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
|
@ -1302,12 +1318,11 @@ void SniffHitag2(bool ledcontrol) {
|
|||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
|
||||
Dbprintf("frame received: %d", frame_count);
|
||||
Dbprintf("Authentication Attempts: %d", (auth_table_len / 8));
|
||||
DBG Dbprintf("frames.......... %d", frame_count);
|
||||
Dbprintf("Auth attempts... %d", (auth_table_len / 8));
|
||||
|
||||
switch_off();
|
||||
BigBuf_free();
|
||||
}
|
||||
|
||||
// Hitag2 simulation
|
||||
|
|
|
@ -450,7 +450,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
|||
Dbprintf("Challenge for UID: %X", temp_uid);
|
||||
temp2++;
|
||||
*txlen = 32;
|
||||
state = _hitag2_init(REV64(tag.key),
|
||||
state = ht2_hitag2_init(REV64(tag.key),
|
||||
REV32((tag.pages[0][3] << 24) + (tag.pages[0][2] << 16) + (tag.pages[0][1] << 8) + tag.pages[0][0]),
|
||||
REV32((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])
|
||||
);
|
||||
|
@ -462,14 +462,14 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
|||
hitagS_set_frame_modulation();
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_hitag2_byte(&state);
|
||||
ht2_hitag2_byte(&state);
|
||||
}
|
||||
|
||||
//send con2, pwdh0, pwdl0, pwdl1 encrypted as a response
|
||||
tx[0] = _hitag2_byte(&state) ^ tag.pages[1][2];
|
||||
tx[1] = _hitag2_byte(&state) ^ tag.pwdh0;
|
||||
tx[2] = _hitag2_byte(&state) ^ tag.pwdl0;
|
||||
tx[3] = _hitag2_byte(&state) ^ tag.pwdl1;
|
||||
tx[0] = ht2_hitag2_byte(&state) ^ tag.pages[1][2];
|
||||
tx[1] = ht2_hitag2_byte(&state) ^ tag.pwdh0;
|
||||
tx[2] = ht2_hitag2_byte(&state) ^ tag.pwdl0;
|
||||
tx[3] = ht2_hitag2_byte(&state) ^ tag.pwdl1;
|
||||
|
||||
if (tag.mode != HT_STANDARD) {
|
||||
//add crc8
|
||||
|
@ -479,7 +479,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
|
|||
calc_crc(&crc, tag.pwdh0, 8);
|
||||
calc_crc(&crc, tag.pwdl0, 8);
|
||||
calc_crc(&crc, tag.pwdl1, 8);
|
||||
tx[4] = (crc ^ _hitag2_byte(&state));
|
||||
tx[4] = (crc ^ ht2_hitag2_byte(&state));
|
||||
}
|
||||
/*
|
||||
* some readers do not allow to authenticate multiple times in a row with the same tag.
|
||||
|
@ -1183,10 +1183,10 @@ static int selectHitagS(hitag_function htf, const hitag_data *htd, uint8_t *tx,
|
|||
((uint64_t)htd->crypto.key[4]) << 32 |
|
||||
((uint64_t)htd->crypto.key[5]) << 40
|
||||
;
|
||||
uint64_t state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
|
||||
uint64_t state = ht2_hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
|
||||
uint8_t auth_ks[4];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
auth_ks[i] = _hitag2_byte(&state) ^ 0xff;
|
||||
auth_ks[i] = ht2_hitag2_byte(&state) ^ 0xff;
|
||||
}
|
||||
|
||||
txlen = 0;
|
||||
|
@ -1239,14 +1239,14 @@ static int selectHitagS(hitag_function htf, const hitag_data *htd, uint8_t *tx,
|
|||
pwdl0 = 0;
|
||||
pwdl1 = 0;
|
||||
if (htf == RHTSF_KEY || htf == WHTSF_KEY) {
|
||||
uint64_t state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
|
||||
uint64_t state = ht2_hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
_hitag2_byte(&state);
|
||||
ht2_hitag2_byte(&state);
|
||||
}
|
||||
uint8_t con2 = rx[0] ^ _hitag2_byte(&state);
|
||||
pwdh0 = rx[1] ^ _hitag2_byte(&state);
|
||||
pwdl0 = rx[2] ^ _hitag2_byte(&state);
|
||||
pwdl1 = rx[3] ^ _hitag2_byte(&state);
|
||||
uint8_t con2 = rx[0] ^ ht2_hitag2_byte(&state);
|
||||
pwdh0 = rx[1] ^ ht2_hitag2_byte(&state);
|
||||
pwdl0 = rx[2] ^ ht2_hitag2_byte(&state);
|
||||
pwdl1 = rx[3] ^ ht2_hitag2_byte(&state);
|
||||
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
Dbprintf("con2 %02X pwdh0 %02X pwdl0 %02X pwdl1 %02X", con2, pwdh0, pwdl0, pwdl1);
|
||||
|
|
|
@ -68,21 +68,6 @@
|
|||
#define BUTTON_DOUBLE_CLICK -2
|
||||
#define BUTTON_ERROR -99
|
||||
|
||||
#ifndef REV8
|
||||
#define REV8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
|
||||
#endif
|
||||
|
||||
#ifndef REV16
|
||||
#define REV16(x) (REV8(x) + (REV8 ((x) >> 8) << 8))
|
||||
#endif
|
||||
|
||||
#ifndef REV32
|
||||
#define REV32(x) (REV16(x) + (REV16((x) >> 16) << 16))
|
||||
#endif
|
||||
|
||||
#ifndef REV64
|
||||
#define REV64(x) (REV32(x) + ((uint64_t)(REV32((x) >> 32) << 32)))
|
||||
#endif
|
||||
|
||||
#ifndef BIT32
|
||||
#define BIT32(x,n) ((((x)[(n)>>5])>>((n)))&1)
|
||||
|
|
|
@ -771,6 +771,7 @@ SRCS += bucketsort.c \
|
|||
crc32.c \
|
||||
crc64.c \
|
||||
commonutil.c \
|
||||
hitag2/hitag2_crypto.c \
|
||||
iso15693tools.c \
|
||||
legic_prng.c \
|
||||
lfdemod.c \
|
||||
|
|
|
@ -3649,6 +3649,51 @@ static int CmdBinaryMap(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdXor(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "data xor",
|
||||
"takes input string and xor string. Perform xor on it.\n"
|
||||
"If no xor string, try the most reoccuring value to xor against",
|
||||
"data xor -d 99aabbcc8888888888\n"
|
||||
"data xor -d 99aabbcc --xor 88888888\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str1("d", "data", "<hex>", "input hex string"),
|
||||
arg_str0("x", "xor", "<str>", "input xor string"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int hlen = 128;
|
||||
uint8_t hex[128 + 1];
|
||||
CLIGetHexWithReturn(ctx, 1, hex, &hlen);
|
||||
|
||||
int xlen = 128;
|
||||
uint8_t xor[128 + 1];
|
||||
CLIGetHexWithReturn(ctx, 2, xor, &xlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// find xor value
|
||||
if (xlen == 0) {
|
||||
uint8_t x = get_highest_frequency(hex, hlen);
|
||||
xlen = hlen;
|
||||
memset(xor, x, xlen);
|
||||
}
|
||||
|
||||
if (hlen != xlen) {
|
||||
PrintAndLogEx(FAILED, "Length mismatch, got %i != %i", hlen, xlen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "input... %s", sprint_hex_inrow(hex, hlen));
|
||||
PrintAndLogEx(SUCCESS, "xor..... %s", sprint_hex_inrow(xor, xlen));
|
||||
hex_xor(hex, xor, hlen);
|
||||
PrintAndLogEx(SUCCESS, "plain... " _YELLOW_("%s"), sprint_hex_inrow(hex, hlen));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "------------------------- " _CYAN_("General") "-------------------------"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
|
@ -3700,9 +3745,10 @@ static command_t CommandTable[] = {
|
|||
{"load", CmdLoad, AlwaysAvailable, "Load contents of file into graph window"},
|
||||
{"num", CmdNumCon, AlwaysAvailable, "Converts dec/hex/bin"},
|
||||
{"print", CmdPrintDemodBuff, AlwaysAvailable, "Print the data in the DemodBuffer"},
|
||||
{"samples", CmdSamples, IfPm3Present, "Get raw samples for graph window (GraphBuffer)"},
|
||||
{"save", CmdSave, AlwaysAvailable, "Save signal trace data (from graph window)"},
|
||||
{"samples", CmdSamples, IfPm3Present, "Get raw samples for graph window ( GraphBuffer )"},
|
||||
{"save", CmdSave, AlwaysAvailable, "Save signal trace data ( GraphBuffer )"},
|
||||
{"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "Set Debugging Level on client side"},
|
||||
{"xor", CmdXor, AlwaysAvailable, "Xor a input string"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -365,7 +365,7 @@ int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool i
|
|||
break;
|
||||
case MIFARE_ULEV1_AUTH:
|
||||
if (cmdsize == 7)
|
||||
snprintf(exp, size, "PWD-AUTH KEY: " _GREEN_("0x%02X%02X%02X%02X"), cmd[1], cmd[2], cmd[3], cmd[4]);
|
||||
snprintf(exp, size, "PWD-AUTH: " _GREEN_("0x%02X%02X%02X%02X"), cmd[1], cmd[2], cmd[3], cmd[4]);
|
||||
else
|
||||
snprintf(exp, size, "PWD-AUTH");
|
||||
break;
|
||||
|
@ -2103,9 +2103,9 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize,
|
|||
break;
|
||||
}
|
||||
|
||||
if ((MifareAuthState == masNone) || (MifareAuthState == masError))
|
||||
if ((MifareAuthState == masNone) || (MifareAuthState == masError)) {
|
||||
annotateIso14443a(exp, size, cmd, cmdsize, isResponse);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void mf_get_paritybinstr(char *s, uint32_t val, uint8_t par) {
|
||||
|
|
|
@ -366,18 +366,16 @@ static void print_hitag2_blocks(uint8_t *d, uint16_t n) {
|
|||
, annotation[i]
|
||||
);
|
||||
}
|
||||
PrintAndLogEx(INFO, "---------+-------------+-------+-----+---------");
|
||||
PrintAndLogEx(INFO, " L = Locked, "_GREEN_("RW") " = Read Write, R = Read Only");
|
||||
PrintAndLogEx(INFO, "--------+-------------+-------+-----+---------");
|
||||
PrintAndLogEx(INFO, " "_RED_("L") " = Locked, "_GREEN_("RW") " = Read Write, R = Read Only");
|
||||
PrintAndLogEx(INFO, " FI = Fixed / Irreversible");
|
||||
PrintAndLogEx(INFO, "-----------------------------------------------");
|
||||
PrintAndLogEx(INFO, "----------------------------------------------");
|
||||
}
|
||||
|
||||
// Annotate HITAG protocol
|
||||
void annotateHitag1(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, bool is_response) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct {
|
||||
enum {
|
||||
STATE_HALT,
|
||||
|
@ -387,16 +385,12 @@ static struct {
|
|||
} state;
|
||||
} _ht2state;
|
||||
|
||||
|
||||
void annotateHitag2_init(void) {
|
||||
_ht2state.state = STATE_HALT;
|
||||
}
|
||||
|
||||
void annotateHitag2(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, uint8_t bits, bool is_response) {
|
||||
|
||||
// I think its better to handle this log bytes as a long array of bits instead.
|
||||
// 1100 0
|
||||
// 1100 0001 1100 0000 00
|
||||
if (cmdsize == 0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
#define HITAG_PASSWORD_SIZE 4
|
||||
#define HITAG_UID_SIZE 4
|
||||
#define HITAG_BLOCK_SIZE 4
|
||||
#define HITAG2_MAX_BYTE_SIZE (12 * HITAG_BLOCK_SIZE)
|
||||
#define HITAG2_MAX_BLOCKS 8
|
||||
#define HITAG2_MAX_BYTE_SIZE (HITAG2_MAX_BLOCKS * HITAG_BLOCK_SIZE)
|
||||
|
||||
// need to see which limits these cards has
|
||||
#define HITAG1_MAX_BYTE_SIZE 64
|
||||
#define HITAGS_MAX_BYTE_SIZE 64
|
||||
|
|
|
@ -650,26 +650,26 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
if (data_len == 1) {
|
||||
|
||||
if (nbits == 5) {
|
||||
snprintf(line[0], 120, "%2u: %02x ", nbits, frame[0] >> (8 - nbits));
|
||||
snprintf(line[0], 120, "%2u: %02X ", nbits, frame[0] >> (8 - nbits));
|
||||
} else {
|
||||
snprintf(line[0], 120, "%2u: %02x ", nbits, frame[0] >> (8 - nbits));
|
||||
snprintf(line[0], 120, "%2u: %02X ", nbits, frame[0] >> (8 - nbits));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (nbits == 0) {
|
||||
snprintf(line[0], 120, "%2u: %02x ", (data_len * 8), frame[0]);
|
||||
snprintf(line[0], 120, "%2u: %02X ", (data_len * 8), frame[0]);
|
||||
} else {
|
||||
snprintf(line[0], 120, "%2u: %02x ", ((data_len - 1) * 8) + nbits, frame[0]);
|
||||
snprintf(line[0], 120, "%2u: %02X ", ((data_len - 1) * 8) + nbits, frame[0]);
|
||||
}
|
||||
}
|
||||
offset = 4;
|
||||
|
||||
} else {
|
||||
snprintf(line[j / 18] + ((j % 18) * 4) + offset, 120, "%02x ", frame[j]);
|
||||
snprintf(line[j / 18] + ((j % 18) * 4) + offset, 120, "%02X ", frame[j]);
|
||||
}
|
||||
|
||||
} else {
|
||||
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x ", frame[j]);
|
||||
snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02X ", frame[j]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -314,19 +314,26 @@ static void PacketResponseReceived(PacketResponseNG *packet) {
|
|||
//PrintAndLogEx(NORMAL, "[" _MAGENTA_("pm3") "] ["_BLUE_("#")"] " "%s", s);
|
||||
PrintAndLogEx(NORMAL, "[" _BLUE_("#") "] %s", s);
|
||||
} else {
|
||||
if (flag & FLAG_INPLACE)
|
||||
if (flag & FLAG_INPLACE) {
|
||||
PrintAndLogEx(NORMAL, "\r" NOLF);
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "%s" NOLF, s);
|
||||
|
||||
if (flag & FLAG_NEWLINE)
|
||||
if (flag & FLAG_NEWLINE) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_DEBUG_PRINT_INTEGERS: {
|
||||
if (packet->ng == false)
|
||||
PrintAndLogEx(NORMAL, "[" _MAGENTA_("pm3") "] ["_BLUE_("#")"] " "%" PRIx64 ", %" PRIx64 ", %" PRIx64 "", packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]);
|
||||
if (packet->ng == false) {
|
||||
PrintAndLogEx(NORMAL, "[" _MAGENTA_("pm3") "] ["_BLUE_("#")"] " "%" PRIx64 ", %" PRIx64 ", %" PRIx64 ""
|
||||
, packet->oldarg[0]
|
||||
, packet->oldarg[1]
|
||||
, packet->oldarg[2]
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// iceman: hw status - down the path on device, runs printusbspeed which starts sending a lot of
|
||||
|
|
|
@ -49,6 +49,23 @@
|
|||
# define NTIME(n) for (int _index = 0; _index < n; _index++)
|
||||
#endif
|
||||
|
||||
#ifndef REV8
|
||||
#define REV8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
|
||||
#endif
|
||||
|
||||
#ifndef REV16
|
||||
#define REV16(x) (REV8(x) + (REV8 ((x) >> 8) << 8))
|
||||
#endif
|
||||
|
||||
#ifndef REV32
|
||||
#define REV32(x) (REV16(x) + (REV16((x) >> 16) << 16))
|
||||
#endif
|
||||
|
||||
#ifndef REV64
|
||||
#define REV64(x) (REV32(x) + ((uint64_t)(REV32((x) >> 32) << 32)))
|
||||
#endif
|
||||
|
||||
|
||||
extern struct version_information_t g_version_information;
|
||||
void FormatVersionInformation(char *dst, int len, const char *prefix, const void *version_info);
|
||||
void format_version_information_short(char *dst, int len, const void *version_info);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "string.h"
|
||||
#include "commonutil.h"
|
||||
|
||||
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
|
||||
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
|
||||
|
@ -35,7 +36,7 @@ static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001
|
|||
static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001
|
||||
static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
|
||||
|
||||
uint32_t _f20(const uint64_t x) {
|
||||
static uint32_t ht2_f20(const uint64_t x) {
|
||||
uint32_t i5;
|
||||
|
||||
i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
|
||||
|
@ -47,18 +48,18 @@ uint32_t _f20(const uint64_t x) {
|
|||
return (ht2_f5c >> i5) & 1;
|
||||
}
|
||||
|
||||
uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) {
|
||||
uint64_t ht2_hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) {
|
||||
uint32_t i;
|
||||
uint64_t x = ((key & 0xFFFF) << 32) + serial;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
x >>= 1;
|
||||
x += (uint64_t)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
|
||||
x += (uint64_t)(ht2_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t _hitag2_round(uint64_t *state) {
|
||||
uint64_t ht2_hitag2_round(uint64_t *state) {
|
||||
uint64_t x = *state;
|
||||
|
||||
x = (x >> 1) +
|
||||
|
@ -68,7 +69,7 @@ uint64_t _hitag2_round(uint64_t *state) {
|
|||
^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47);
|
||||
|
||||
*state = x;
|
||||
return _f20(x);
|
||||
return ht2_f20(x);
|
||||
}
|
||||
|
||||
// "MIKRON" = O N M I K R
|
||||
|
@ -81,15 +82,15 @@ uint64_t _hitag2_round(uint64_t *state) {
|
|||
// The inverse of the first 4 bytes is sent to the tag to authenticate.
|
||||
// The rest is encrypted by XORing it with the subsequent keystream.
|
||||
|
||||
uint32_t _hitag2_byte(uint64_t *x) {
|
||||
uint32_t ht2_hitag2_byte(uint64_t *x) {
|
||||
uint32_t i, c;
|
||||
for (i = 0, c = 0; i < 8; i++) {
|
||||
c += (uint32_t) _hitag2_round(x) << (i ^ 7);
|
||||
c += (uint32_t) ht2_hitag2_round(x) << (i ^ 7);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) {
|
||||
void ht2_hitag2_cipher_reset(hitag2_t *tag, const uint8_t *iv) {
|
||||
uint64_t key = ((uint64_t)tag->sectors[2][2]) |
|
||||
((uint64_t)tag->sectors[2][3] << 8) |
|
||||
((uint64_t)tag->sectors[1][0] << 16) |
|
||||
|
@ -104,22 +105,22 @@ void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) {
|
|||
(((uint32_t)(iv[1])) << 8) |
|
||||
(((uint32_t)(iv[2])) << 16) |
|
||||
(((uint32_t)(iv[3])) << 24);
|
||||
tag->cs = _hitag2_init(REV64(key), REV32(uid), REV32(iv_));
|
||||
tag->cs = ht2_hitag2_init(REV64(key), REV32(uid), REV32(iv_));
|
||||
}
|
||||
|
||||
int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) {
|
||||
int ht2_hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) {
|
||||
uint8_t authenticator_should[4];
|
||||
authenticator_should[0] = ~_hitag2_byte(cs);
|
||||
authenticator_should[1] = ~_hitag2_byte(cs);
|
||||
authenticator_should[2] = ~_hitag2_byte(cs);
|
||||
authenticator_should[3] = ~_hitag2_byte(cs);
|
||||
authenticator_should[0] = ~ht2_hitag2_byte(cs);
|
||||
authenticator_should[1] = ~ht2_hitag2_byte(cs);
|
||||
authenticator_should[2] = ~ht2_hitag2_byte(cs);
|
||||
authenticator_should[3] = ~ht2_hitag2_byte(cs);
|
||||
return (memcmp(authenticator_should, authenticator_is, 4) == 0);
|
||||
}
|
||||
|
||||
int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) {
|
||||
int ht2_hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) {
|
||||
int i;
|
||||
for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs);
|
||||
for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i);
|
||||
for (i = 0; i < bytes; i++) data[i] ^= ht2_hitag2_byte(cs);
|
||||
for (i = 0; i < bits; i++) data[bytes] ^= ht2_hitag2_round(cs) << (7 - i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
struct hitag2_tag {
|
||||
typedef struct {
|
||||
uint32_t uid;
|
||||
enum {
|
||||
TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr
|
||||
|
@ -30,14 +30,13 @@ struct hitag2_tag {
|
|||
uint8_t crypto_active;
|
||||
uint64_t cs;
|
||||
uint8_t sectors[12][4];
|
||||
};
|
||||
} hitag2_t;
|
||||
|
||||
uint32_t _f20(const uint64_t x);
|
||||
uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV);
|
||||
uint64_t _hitag2_round(uint64_t *state);
|
||||
uint32_t _hitag2_byte(uint64_t *x);
|
||||
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv);
|
||||
int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is);
|
||||
int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ;
|
||||
uint64_t ht2_hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV);
|
||||
uint64_t ht2_hitag2_round(uint64_t *state);
|
||||
uint32_t ht2_hitag2_byte(uint64_t *x);
|
||||
void ht2_hitag2_cipher_reset(hitag2_t *tag, const uint8_t *iv);
|
||||
int ht2_hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is);
|
||||
int ht2_hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,7 +44,7 @@ OBJDIR = obj
|
|||
INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I.
|
||||
|
||||
# Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the lz4 directory
|
||||
VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga ../armsrc/Standalone
|
||||
VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga ../armsrc/Standalone ../common/hitag2
|
||||
|
||||
INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h
|
||||
|
||||
|
|
|
@ -914,7 +914,6 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define HITAG2_WRITE_PAGE "10" // write page after auth
|
||||
#define HITAG2_HALT "00" // silence currently authenticated tag
|
||||
|
||||
|
||||
// HITAG S commands
|
||||
#define HITAGS_QUIET 0x70
|
||||
//inverted in bit 0 and following 2 bits
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue