*.dll
*.moc.cpp
*.z
+version.c
+
*.exe
-proxmark
proxmark3
flasher
-version.c
lua
luac
fpga_compress
+mfkey32
+mfkey64
fpga/*
!fpga/tests
!fpga/xst_hf.scr
!fpga/go.bat
!fpga/sim.tcl
-
-
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
SRC_ISO14443b = iso14443b.c
SRC_CRAPTO1 = crypto1.c des.c aes.c
-SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
+SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c
#the FPGA bitstream files. Note: order matters!
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
#include "mifareutil.h"
#include "BigBuf.h"
#include "protocols.h"
+#include "parity.h"
+
static uint32_t iso14a_timeout;
int rsamples = 0;
#define SEC_Y 0x00
#define SEC_Z 0xc0
-const uint8_t OddByteParity[256] = {
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
- 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
-};
-
void iso14a_set_trigger(bool enable) {
trigger = enable;
// Generate the parity value for a byte sequence
//
//-----------------------------------------------------------------------------
-byte_t oddparity (const byte_t bt)
-{
- return OddByteParity[bt];
-}
-
void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par)
{
uint16_t paritybit_cnt = 0;
for (uint16_t i = 0; i < iLen; i++) {
// Generate the parity bits
- parityBits |= ((OddByteParity[pbtCmd[i]]) << (7-paritybit_cnt));
+ parityBits |= ((oddparity8(pbtCmd[i])) << (7-paritybit_cnt));
if (paritybit_cnt == 7) {
par[paritybyte_cnt] = parityBits; // save 8 Bits parity
parityBits = 0; // and advance to next Parity Byte
#ifndef __ISO14443A_H
#define __ISO14443A_H
+
#include "common.h"
#include "mifaresniff.h"
} tUart;
-
-extern byte_t oddparity (const byte_t bt);
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
extern void AppendCrc14443a(uint8_t *data, int len);
#include "mifarecmd.h"\r
#include "apps.h"\r
#include "util.h"\r
+#include "parity.h"\r
#include "crc.h"\r
\r
// the block number for the ISO14443-4 PCB\r
\r
// Return 1 if the nonce is invalid else return 0\r
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {\r
- return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \\r
- (oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \\r
- (oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;\r
+ return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \\r
+ (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \\r
+ (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;\r
}\r
\r
\r
\r
// Parity validity check\r
for (j = 0; j < 4; j++) {\r
- par_array[j] = (oddparity(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));\r
+ par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));\r
}\r
\r
ncount = 0;\r
#include "proxmark3.h"\r
#include "apps.h"\r
#include "util.h"\r
+#include "parity.h"\r
#include "string.h"\r
\r
#include "iso14443crc.h"\r
data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];\r
if((i&0x0007) == 0) \r
par[i>>3] = 0;\r
- par[i>>3] |= (((filter(pcs->odd) ^ oddparity(bt)) & 0x01)<<(7-(i&0x0007)));\r
+ par[i>>3] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007)));\r
} \r
return;\r
}\r
for (pos = 0; pos < 4; pos++)\r
{\r
ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];\r
- par[0] |= (((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) << (7-pos));\r
+ par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos));\r
} \r
\r
ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);\r
for (pos = 0; pos < 4; pos++)\r
{\r
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];\r
- par[0] |= (((filter(pcs->odd) ^ oddparity(nr[pos])) & 0x01) << (7-pos));\r
+ par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos));\r
} \r
\r
// Skip 32 bits in pseudo random generator\r
{\r
nt = prng_successor(nt,8);\r
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);\r
- par[0] |= (((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) << (7-pos));\r
+ par[0] |= (((filter(pcs->odd) ^ oddparity8(nt)) & 0x01) << (7-pos));\r
} \r
\r
// Transmit reader nonce and reader answer\r
for (pos = 0; pos < 18; pos++)\r
{\r
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];\r
- par[pos>>3] |= (((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));\r
+ par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));\r
} \r
\r
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);\r
CMDSRCS = crapto1/crapto1.c\
crapto1/crypto1.c\
- nonce2key.c\
+ mfkey.c\
loclass/cipher.c \
loclass/cipherutils.c \
loclass/des.c \
loclass/fileutils.c\
whereami.c\
mifarehost.c\
+ parity.c\
crc.c \
crc16.c \
crc64.c \
#include "data.h"
#include "ui.h"
#include "iso14443crc.h"
+#include "parity.h"
#include "cmdmain.h"
#include "cmdparser.h"
#include "cmdhf.h"
for (int j = 0; j < data_len && j/16 < 16; j++) {
- int oddparity = 0x01;
- int k;
-
- for (k=0 ; k<8 ; k++) {
- oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
- }
uint8_t parityBits = parityBytes[j>>3];
- if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+ if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity8(frame[j]) != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
} else {
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
#include "ui.h"\r
#include "mifarehost.h"\r
#include "mifare.h"\r
-#include "nonce2key.h"\r
+#include "mfkey.h"\r
\r
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up\r
\r
#include "cmdparser.h"
#include "common.h"
#include "util.h"
+#include "parity.h"
#include "hitag2.h"
#include "hitagS.h"
#include "cmdmain.h"
char line[1000] = "";
int j;
for (j = 0; j < len; j++) {
- int oddparity = 0x01;
- int k;
-
- for (k=0;k<8;k++) {
- oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
- }
//if((parityBits >> (len - j - 1)) & 0x01) {
- if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
+ if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) {
sprintf(line+(j*4), "%02x! ", frame[j]);
}
else {
--- /dev/null
+//-----------------------------------------------------------------------------
+// Merlok - June 2011
+// Roel - Dec 2009
+// Unknown author
+//
+// 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.
+//-----------------------------------------------------------------------------
+// MIFARE Darkside hack
+//-----------------------------------------------------------------------------
+
+#include "mfkey.h"
+
+#include "crapto1/crapto1.h"
+
+
+// recover key from 2 different reader responses on same tag challenge
+bool mfkey32(nonces_t data, uint64_t *outputkey) {
+ struct Crypto1State *s,*t;
+ uint64_t outkey = 0;
+ uint64_t key = 0; // recovered key
+ bool isSuccess = false;
+ uint8_t counter = 0;
+
+ s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
+
+ for(t = s; t->odd | t->even; ++t) {
+ lfsr_rollback_word(t, 0, 0);
+ lfsr_rollback_word(t, data.nr, 1);
+ lfsr_rollback_word(t, data.cuid ^ data.nonce, 0);
+ crypto1_get_lfsr(t, &key);
+ crypto1_word(t, data.cuid ^ data.nonce, 0);
+ crypto1_word(t, data.nr2, 1);
+ if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce, 64))) {
+ //PrintAndLog("Found Key: [%012" PRIx64 "]",key);
+ outkey = key;
+ counter++;
+ if (counter == 20) break;
+ }
+ }
+ isSuccess = (counter == 1);
+ *outputkey = ( isSuccess ) ? outkey : 0;
+ crypto1_destroy(s);
+ /* //un-comment to save all keys to a stats.txt file
+ FILE *fout;
+ if ((fout = fopen("stats.txt","ab")) == NULL) {
+ PrintAndLog("Could not create file name stats.txt");
+ return 1;
+ }
+ fprintf(fout, "mfkey32,%d,%08x,%d,%s,%04x%08x,%.0Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t)(outkey>>32) & 0xFFFF,(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
+ fclose(fout);
+ */
+ return isSuccess;
+}
+
+// recover key from 2 reader responses on 2 different tag challenges
+bool mfkey32_moebius(nonces_t data, uint64_t *outputkey) {
+ struct Crypto1State *s, *t;
+ uint64_t outkey = 0;
+ uint64_t key = 0; // recovered key
+ bool isSuccess = false;
+ int counter = 0;
+
+ s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
+
+ for(t = s; t->odd | t->even; ++t) {
+ lfsr_rollback_word(t, 0, 0);
+ lfsr_rollback_word(t, data.nr, 1);
+ lfsr_rollback_word(t, data.cuid ^ data.nonce, 0);
+ crypto1_get_lfsr(t, &key);
+
+ crypto1_word(t, data.cuid ^ data.nonce2, 0);
+ crypto1_word(t, data.nr2, 1);
+ if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce2, 64))) {
+ //PrintAndLog("Found Key: [%012" PRIx64 "]",key);
+ outkey=key;
+ ++counter;
+ if (counter==20)
+ break;
+ }
+ }
+ isSuccess = (counter == 1);
+ *outputkey = ( isSuccess ) ? outkey : 0;
+ crypto1_destroy(s);
+ /* // un-comment to output all keys to stats.txt
+ FILE *fout;
+ if ((fout = fopen("stats.txt","ab")) == NULL) {
+ PrintAndLog("Could not create file name stats.txt");
+ return 1;
+ }
+ fprintf(fout, "moebius,%d,%08x,%d,%s,%04x%08x,%0.Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t) (outkey>>32),(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
+ fclose(fout);
+ */
+ return isSuccess;
+}
+
+// recover key from reader response and tag response of one authentication sequence
+int mfkey64(nonces_t data, uint64_t *outputkey){
+ uint64_t key = 0; // recovered key
+ uint32_t ks2; // keystream used to encrypt reader response
+ uint32_t ks3; // keystream used to encrypt tag response
+ struct Crypto1State *revstate;
+
+ // Extract the keystream from the messages
+ ks2 = data.ar ^ prng_successor(data.nonce, 64);
+ ks3 = data.at ^ prng_successor(data.nonce, 96);
+ revstate = lfsr_recovery64(ks2, ks3);
+ lfsr_rollback_word(revstate, 0, 0);
+ lfsr_rollback_word(revstate, 0, 0);
+ lfsr_rollback_word(revstate, data.nr, 1);
+ lfsr_rollback_word(revstate, data.cuid ^ data.nonce, 0);
+ crypto1_get_lfsr(revstate, &key);
+ // PrintAndLog("Found Key: [%012" PRIx64 "]", key);
+ crypto1_destroy(revstate);
+ *outputkey = key;
+
+ return 0;
+}
+
+
--- /dev/null
+//-----------------------------------------------------------------------------
+// Merlok - June 2011
+// Roel - Dec 2009
+// Unknown author
+//
+// 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.
+//-----------------------------------------------------------------------------
+// MIFARE Darkside hack
+//-----------------------------------------------------------------------------
+
+#ifndef MFKEY_H
+#define MFKEY_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct {
+ uint32_t cuid;
+ uint8_t sector;
+ uint8_t keytype;
+ uint32_t nonce;
+ uint32_t ar;
+ uint32_t nr;
+ uint32_t at;
+ uint32_t nonce2;
+ uint32_t ar2;
+ uint32_t nr2;
+ } nonces_t;
+
+extern bool mfkey32(nonces_t data, uint64_t *outputkey);
+extern bool mfkey32_moebius(nonces_t data, uint64_t *outputkey);
+extern int mfkey64(nonces_t data, uint64_t *outputkey);
+
+#endif
// mifare commands\r
//-----------------------------------------------------------------------------\r
\r
+#include "mifarehost.h"\r
+\r
#include <stdio.h>\r
#include <stdlib.h> \r
#include <string.h>\r
#include "ui.h"\r
#include "util.h"\r
#include "iso14443crc.h"\r
-#include "mifarehost.h"\r
\r
// mifare tracer flags used in mfTraceDecode()\r
#define TRACE_IDLE 0x00\r
// High frequency ISO14443A commands\r
//-----------------------------------------------------------------------------\r
\r
+#ifndef MIFAREHOST_H\r
+#define MIFAREHOST_H\r
+\r
#include <stdint.h>\r
#include <stdbool.h>\r
#include "data.h"\r
extern int loadTraceCard(uint8_t *tuid);\r
extern int saveTraceCard(void);\r
extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);\r
+\r
+#endif\r
+++ /dev/null
-//-----------------------------------------------------------------------------
-// Merlok - June 2011
-// Roel - Dec 2009
-// Unknown author
-//
-// 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.
-//-----------------------------------------------------------------------------
-// MIFARE Darkside hack
-//-----------------------------------------------------------------------------
-
-#include "nonce2key.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "mifarehost.h"
-#include "util.h"
-#include "crapto1/crapto1.h"
-
-// recover key from 2 different reader responses on same tag challenge
-bool mfkey32(nonces_t data, uint64_t *outputkey) {
- struct Crypto1State *s,*t;
- uint64_t outkey = 0;
- uint64_t key = 0; // recovered key
- bool isSuccess = false;
- uint8_t counter = 0;
-
- uint64_t t1 = msclock();
-
- s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
-
- for(t = s; t->odd | t->even; ++t) {
- lfsr_rollback_word(t, 0, 0);
- lfsr_rollback_word(t, data.nr, 1);
- lfsr_rollback_word(t, data.cuid ^ data.nonce, 0);
- crypto1_get_lfsr(t, &key);
- crypto1_word(t, data.cuid ^ data.nonce, 0);
- crypto1_word(t, data.nr2, 1);
- if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce, 64))) {
- //PrintAndLog("Found Key: [%012" PRIx64 "]",key);
- outkey = key;
- counter++;
- if (counter == 20) break;
- }
- }
- isSuccess = (counter == 1);
- t1 = msclock() - t1;
- //if ( t1 > 0 ) PrintAndLog("Time in mfkey32: %.1f seconds \nFound %d possible keys", (float)t1/1000.0, counter);
- *outputkey = ( isSuccess ) ? outkey : 0;
- crypto1_destroy(s);
- /* //un-comment to save all keys to a stats.txt file
- FILE *fout;
- if ((fout = fopen("stats.txt","ab")) == NULL) {
- PrintAndLog("Could not create file name stats.txt");
- return 1;
- }
- fprintf(fout, "mfkey32,%d,%08x,%d,%s,%04x%08x,%.0Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t)(outkey>>32) & 0xFFFF,(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
- fclose(fout);
- */
- return isSuccess;
-}
-
-// recover key from 2 reader responses on 2 different tag challenges
-bool mfkey32_moebius(nonces_t data, uint64_t *outputkey) {
- struct Crypto1State *s, *t;
- uint64_t outkey = 0;
- uint64_t key = 0; // recovered key
- bool isSuccess = false;
- int counter = 0;
-
- //PrintAndLog("Enter mfkey32_moebius");
- uint64_t t1 = msclock();
-
- s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
-
- for(t = s; t->odd | t->even; ++t) {
- lfsr_rollback_word(t, 0, 0);
- lfsr_rollback_word(t, data.nr, 1);
- lfsr_rollback_word(t, data.cuid ^ data.nonce, 0);
- crypto1_get_lfsr(t, &key);
-
- crypto1_word(t, data.cuid ^ data.nonce2, 0);
- crypto1_word(t, data.nr2, 1);
- if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce2, 64))) {
- //PrintAndLog("Found Key: [%012" PRIx64 "]",key);
- outkey=key;
- ++counter;
- if (counter==20)
- break;
- }
- }
- isSuccess = (counter == 1);
- t1 = msclock() - t1;
- // PrintAndLog("Time in mfkey32_moebius: %.1f seconds \nFound %d possible keys", (float)t1/1000.0, counter);
- *outputkey = ( isSuccess ) ? outkey : 0;
- crypto1_destroy(s);
- /* // un-comment to output all keys to stats.txt
- FILE *fout;
- if ((fout = fopen("stats.txt","ab")) == NULL) {
- PrintAndLog("Could not create file name stats.txt");
- return 1;
- }
- fprintf(fout, "moebius,%d,%08x,%d,%s,%04x%08x,%0.Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t) (outkey>>32),(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
- fclose(fout);
- */
- return isSuccess;
-}
-
-// recover key from reader response and tag response of one authentication sequence
-int mfkey64(nonces_t data, uint64_t *outputkey){
- uint64_t key = 0; // recovered key
- uint32_t ks2; // keystream used to encrypt reader response
- uint32_t ks3; // keystream used to encrypt tag response
- struct Crypto1State *revstate;
-
- // PrintAndLog("Enter mfkey64");
- uint64_t t1 = msclock();
-
- // Extract the keystream from the messages
- ks2 = data.ar ^ prng_successor(data.nonce, 64);
- ks3 = data.at ^ prng_successor(data.nonce, 96);
- revstate = lfsr_recovery64(ks2, ks3);
- lfsr_rollback_word(revstate, 0, 0);
- lfsr_rollback_word(revstate, 0, 0);
- lfsr_rollback_word(revstate, data.nr, 1);
- lfsr_rollback_word(revstate, data.cuid ^ data.nonce, 0);
- crypto1_get_lfsr(revstate, &key);
- // PrintAndLog("Found Key: [%012" PRIx64 "]", key);
- crypto1_destroy(revstate);
- *outputkey = key;
-
- t1 = msclock() - t1;
- // PrintAndLog("Time in mfkey64: %.1f seconds \n", (float)t1/1000.0);
- return 0;
-}
+++ /dev/null
-//-----------------------------------------------------------------------------
-// Merlok - June 2011
-// Roel - Dec 2009
-// Unknown author
-//
-// 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.
-//-----------------------------------------------------------------------------
-// MIFARE Darkside hack
-//-----------------------------------------------------------------------------
-
-#ifndef __NONCE2KEY_H
-#define __NONCE2KEY_H
-
-#include <stdint.h>
-#include <stdbool.h>
-
-typedef struct {
- uint32_t cuid;
- uint8_t sector;
- uint8_t keytype;
- uint32_t nonce;
- uint32_t ar;
- uint32_t nr;
- uint32_t at;
- uint32_t nonce2;
- uint32_t ar2;
- uint32_t nr2;
- } nonces_t;
-
-bool mfkey32(nonces_t data, uint64_t *outputkey);
-bool mfkey32_moebius(nonces_t data, uint64_t *outputkey);
-int mfkey64(nonces_t data, uint64_t *outputkey);
-
-#endif
#ifndef _WIN32
#include <termios.h>
#include <sys/ioctl.h>
+#include <unistd.h>
int ukbhit(void)
{
int error;
static struct termios Otty, Ntty;
-
- if ( tcgetattr( 0, &Otty) == -1 ) return -1;
+ if ( tcgetattr(STDIN_FILENO, &Otty) == -1 ) return -1;
Ntty = Otty;
- Ntty.c_iflag = 0; /* input mode */
- Ntty.c_oflag = 0; /* output mode */
- Ntty.c_lflag &= ~ICANON; /* raw mode */
- Ntty.c_cc[VMIN] = CMIN; /* minimum time to wait */
- Ntty.c_cc[VTIME] = CTIME; /* minimum characters to wait for */
-
- if (0 == (error = tcsetattr(0, TCSANOW, &Ntty))) {
- error += ioctl(0, FIONREAD, &cnt);
- error += tcsetattr(0, TCSANOW, &Otty);
+ Ntty.c_iflag = 0x0000; // input mode
+ Ntty.c_oflag = 0x0000; // output mode
+ Ntty.c_lflag &= ~ICANON; // control mode = raw
+ Ntty.c_cc[VMIN] = 1; // return if at least 1 character is in the queue
+ Ntty.c_cc[VTIME] = 0; // no timeout. Wait forever
+
+ if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) { // set new attributes
+ error += ioctl(STDIN_FILENO, FIONREAD, &cnt); // get number of characters availabe
+ error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes
}
return ( error == 0 ? cnt : -1 );
Copyright (C) 2008-2014 bla <blapost@gmail.com>
*/
#include "crapto1.h"
+
#include <stdlib.h>
+#include "parity.h"
#if !defined LOWMEM && defined __GNUC__
static uint8_t filterlut[1 << 20];
{
uint32_t p = *item >> 25;
- p = p << 1 | parity(*item & mask1);
- p = p << 1 | parity(*item & mask2);
+ p = p << 1 | evenparity32(*item & mask1);
+ p = p << 1 | evenparity32(*item & mask2);
*item = p << 24 | (*item & 0xffffff);
}
if(rem == -1) {
for(e = e_head; e <= e_tail; ++e) {
- *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4);
+ *e = *e << 1 ^ evenparity32(*e & LF_POLY_EVEN) ^ !!(in & 4);
for(o = o_head; o <= o_tail; ++o, ++sl) {
sl->even = *o;
- sl->odd = *e ^ parity(*o & LF_POLY_ODD);
+ sl->odd = *e ^ evenparity32(*o & LF_POLY_ODD);
sl[1].odd = sl[1].even = 0;
}
}
continue;
for(j = 0; j < 19; ++j)
- low = low << 1 | parity(i & S1[j]);
+ low = low << 1 | evenparity32(i & S1[j]);
for(j = 0; j < 32; ++j)
- hi[j] = parity(i & T1[j]);
+ hi[j] = evenparity32(i & T1[j]);
for(; tail >= table; --tail) {
for(j = 0; j < 3; ++j) {
*tail = *tail << 1;
- *tail |= parity((i & C1[j]) ^ (*tail & C2[j]));
+ *tail |= evenparity32((i & C1[j]) ^ (*tail & C2[j]));
if(filter(*tail) != oks[29 + j])
goto continue2;
}
for(j = 0; j < 19; ++j)
- win = win << 1 | parity(*tail & S2[j]);
+ win = win << 1 | evenparity32(*tail & S2[j]);
win ^= low;
for(j = 0; j < 32; ++j) {
- win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]);
+ win = win << 1 ^ hi[j] ^ evenparity32(*tail & T2[j]);
if(filter(win) != eks[j])
goto continue2;
}
- *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail);
- sl->odd = *tail ^ parity(LF_POLY_ODD & win);
+ *tail = *tail << 1 | evenparity32(LF_POLY_EVEN & *tail);
+ sl->odd = *tail ^ evenparity32(LF_POLY_ODD & win);
sl->even = win;
++sl;
sl->odd = sl->even = 0;
out ^= !!in;
out ^= (ret = filter(s->odd)) & !!fb;
- s->even |= parity(out) << 23;
+ s->even |= evenparity32(out) << 23;
return ret;
}
/** lfsr_rollback_byte
nr = ks1 ^ (prefix | c << 5);
rr = ks2 ^ rresp;
- good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24);
- good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16);
- good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8);
- good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0);
- good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3;
+ good &= evenparity32(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24);
+ good &= evenparity32(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16);
+ good &= evenparity32(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8);
+ good &= evenparity32(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0);
+ good &= evenparity32(rr & 0x000000ff) ^ parities[c][7] ^ ks3;
}
return sl + good;
#endif
struct Crypto1State {uint32_t odd, even;};
-#if defined(__arm__)
+#if defined(__arm__) && !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free()
void crypto1_create(struct Crypto1State *s, uint64_t key);
#else
struct Crypto1State *crypto1_create(uint64_t key);
int __i;\
for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\
for(__i = FSIZE - 1; __i >= 0; __i--)\
- if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\
+ if(BIT(FILTER, __i) ^ evenparity32(__M & 0xFF01))\
break;\
else if(__i)\
__M = prng_successor(__M, (__i == 7) ? 48 : 8);\
#define LF_POLY_EVEN (0x870804)
#define BIT(x, n) ((x) >> (n) & 1)
#define BEBIT(x, n) BIT(x, (n) ^ 24)
-static inline int parity(uint32_t x)
-{
-#if !defined __i386__ || !defined __GNUC__
- x ^= x >> 16;
- x ^= x >> 8;
- x ^= x >> 4;
- return BIT(0x6996, x & 0xf);
-#else
- __asm( "movl %1, %%eax\n"
- "mov %%ax, %%cx\n"
- "shrl $0x10, %%eax\n"
- "xor %%ax, %%cx\n"
- "xor %%ch, %%cl\n"
- "setpo %%al\n"
- "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx");
- return x;
-#endif
-}
static inline int filter(uint32_t const x)
{
uint32_t f;
Copyright (C) 2008-2008 bla <blapost@gmail.com>
*/
#include "crapto1.h"
+
#include <stdlib.h>
+#include "parity.h"
#define SWAPENDIAN(x)\
(x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16)
-#if defined(__arm__) && !defined(__linux__) && !defined(_WIN32) // bare metal ARM lacks malloc()/free()
+#if defined(__arm__) && !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free()
void crypto1_create(struct Crypto1State *s, uint64_t key)
{
int i;
feedin ^= !!in;
feedin ^= LF_POLY_ODD & s->odd;
feedin ^= LF_POLY_EVEN & s->even;
- s->even = s->even << 1 | parity(feedin);
+ s->even = s->even << 1 | evenparity32(feedin);
t = s->odd, s->odd = s->even, s->even = t;
--- /dev/null
+CRAPTO1
+-------
+ Provides a set of library functions which aid the verification
+ of crypto1 weaknesses.
+
+ In short a partial implementation of:
+ Dismantling MIFARE Classic
+ URL: http://www.sos.cs.ru.nl/applications/rfid/2008-esorics.pdf
+ Flavio D. Garcia, Gerhard de Koning Gans, Ruben Muijrers,
+ Peter van Rossum, Roel Verdult, Ronny Wichers Schreur, Bart Jacobs
+ Institute for Computing and Information Sciences,
+ Radboud University Nijmegen, The Netherlands
+ {{flaviog,petervr,ronny,bart}@cs, {gkoningg,rmuijrer,rverdult}@sci}.ru.nl
+ and
+ Wirelessly Pickpocketing a Mifare Classic Card
+ URL: http://www.cs.ru.nl/~flaviog/publications/Pickpocketing.Mifare.pdf
+ Flavio D. Garcia, Peter van Rossum, Roel Verdult, Ronny Wichers Schreur
+ Radboud University Nijmegen, The Netherlands
+ {flaviog,petervr,rverdult,ronny}@cs.ru.nl
+ and
+ THE DARK SIDE OF SECURITY BY OBSCURITY
+ URL: http://eprint.iacr.org/2009/137
+ and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime
+ Nicolas T. Courtois
+ University College London, Computer Science,
+ Gower street, WC1E 6BT, London, UK
+
--- /dev/null
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+// parity functions (all defined in parity.h)
+//-----------------------------------------------------------------------------
+
+#include <stdint.h>
+
+const uint8_t OddByteParity[256] = {
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
--- /dev/null
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+// Parity functions
+//-----------------------------------------------------------------------------
+
+// all functions defined in header file by purpose. Allows compiler optimizations.
+
+#ifndef __PARITY_H
+#define __PARITY_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+extern const uint8_t OddByteParity[256];
+
+
+static inline bool oddparity8(const uint8_t x) {
+ return OddByteParity[x];
+}
+
+
+static inline bool evenparity8(const uint8_t x) {
+ return !OddByteParity[x];
+}
+
+
+static inline bool evenparity32(uint32_t x)
+{
+#if !defined __GNUC__
+ x ^= x >> 16;
+ x ^= x >> 8;
+ return evenparity8(x);
+#else
+ return __builtin_parity(x);
+#endif
+}
+
+
+static inline bool oddparity32(uint32_t x)
+{
+#if !defined __GNUC__
+ x ^= x >> 16;
+ x ^= x >> 8;
+ return oddparity8(x);
+#else
+ return !__builtin_parity(x);
+#endif
+}
+
+#endif /* __PARITY_H */
-VPATH = ../../common/crapto1
+VPATH = ../../common ../../common/crapto1 ../../client
CC = gcc
LD = gcc
-CFLAGS = -I../../common -Wall -O4
+CFLAGS = -std=c99 -D_ISOC99_SOURCE -I../../common -I../../client -Wall -O3
LDFLAGS =
-OBJS = crypto1.o crapto1.o
+OBJS = crypto1.o crapto1.o parity.o util.o mfkey.o
EXES = mfkey32 mfkey64
WINEXES = $(patsubst %, %.exe, $(EXES))
%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
-% : %.c
+% : %.c $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $<
clean:
#include <inttypes.h>
-#include "crapto1/crapto1.h"
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include "crapto1/crapto1.h"
+#include "mfkey.h"
+#include "util.h"
+// 32 bit recover key from 2 nonces
int main (int argc, char *argv[]) {
- struct Crypto1State *s,*t;
- uint64_t key; // recovered key
- uint32_t uid; // serial number
- uint32_t nt; // tag challenge
- uint32_t nr0_enc; // first encrypted reader challenge
- uint32_t ar0_enc; // first encrypted reader response
- uint32_t nr1_enc; // second encrypted reader challenge
- uint32_t ar1_enc; // second encrypted reader response
+
+ nonces_t data;
uint32_t ks2; // keystream used to encrypt reader response
+ uint64_t key; // recovered key
- printf("MIFARE Classic key recovery - based 32 bits of keystream\n");
+ printf("MIFARE Classic key recovery - based on 32 bits of keystream\n");
printf("Recover key from two 32-bit reader authentication answers only!\n\n");
- if (argc < 7) {
- printf(" syntax: %s <uid> <nt> <{nr_0}> <{ar_0}> <{nr_1}> <{ar_1}>\n\n",argv[0]);
+ if (argc != 7 && argc != 8) {
+ printf(" syntax: %s <uid> <nt0> <{nr_0}> <{ar_0}> [<nt1>] <{nr_1}> <{ar_1}>\n", argv[0]);
+ printf(" (you may omit nt1 if it is equal to nt0)\n\n");
return 1;
}
- sscanf(argv[1],"%x",&uid);
- sscanf(argv[2],"%x",&nt);
- sscanf(argv[3],"%x",&nr0_enc);
- sscanf(argv[4],"%x",&ar0_enc);
- sscanf(argv[5],"%x",&nr1_enc);
- sscanf(argv[6],"%x",&ar1_enc);
+ bool moebius_attack = (argc == 8);
+
+ sscanf(argv[1],"%x",&data.cuid);
+ sscanf(argv[2],"%x",&data.nonce);
+ data.nonce2 = data.nonce;
+ sscanf(argv[3],"%x",&data.nr);
+ sscanf(argv[4],"%x",&data.ar);
+ if (moebius_attack) {
+ sscanf(argv[5],"%x",&data.nonce2);
+ sscanf(argv[6],"%x",&data.nr2);
+ sscanf(argv[7],"%x",&data.ar2);
+ } else {
+ sscanf(argv[5],"%x",&data.nr2);
+ sscanf(argv[6],"%x",&data.ar2);
+ }
printf("Recovering key for:\n");
- printf(" uid: %08x\n",uid);
- printf(" nt: %08x\n",nt);
- printf(" {nr_0}: %08x\n",nr0_enc);
- printf(" {ar_0}: %08x\n",ar0_enc);
- printf(" {nr_1}: %08x\n",nr1_enc);
- printf(" {ar_1}: %08x\n",ar1_enc);
+ printf(" uid: %08x\n",data.cuid);
+ printf(" nt0: %08x\n",data.nonce);
+ printf(" {nr_0}: %08x\n",data.nr);
+ printf(" {ar_0}: %08x\n",data.ar);
+ printf(" nt1: %08x\n",data.nonce2);
+ printf(" {nr_1}: %08x\n",data.nr2);
+ printf(" {ar_1}: %08x\n",data.ar2);
+ uint64_t start_time = msclock();
+
// Generate lfsr succesors of the tag challenge
printf("\nLFSR succesors of the tag challenge:\n");
- printf(" nt': %08x\n",prng_successor(nt, 64));
- printf(" nt'': %08x\n",prng_successor(nt, 96));
+ printf(" nt': %08x\n",prng_successor(data.nonce, 64));
+ printf(" nt'': %08x\n",prng_successor(data.nonce, 96));
// Extract the keystream from the messages
printf("\nKeystream used to generate {ar} and {at}:\n");
- ks2 = ar0_enc ^ prng_successor(nt, 64);
+ ks2 = data.ar ^ prng_successor(data.nonce, 64);
printf(" ks2: %08x\n",ks2);
- s = lfsr_recovery32(ar0_enc ^ prng_successor(nt, 64), 0);
-
- for(t = s; t->odd | t->even; ++t) {
- lfsr_rollback_word(t, 0, 0);
- lfsr_rollback_word(t, nr0_enc, 1);
- lfsr_rollback_word(t, uid ^ nt, 0);
- crypto1_get_lfsr(t, &key);
- crypto1_word(t, uid ^ nt, 0);
- crypto1_word(t, nr1_enc, 1);
- if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt, 64))) {
- printf("\nFound Key: [%012" PRIx64 "]\n\n",key);
- break;
- }
+ bool success;
+ if (moebius_attack) {
+ success = mfkey32_moebius(data, &key);
+ } else {
+ success = mfkey32(data, &key);
+ }
+
+ if (success) {
+ printf("Recovered key: %012" PRIx64 "\n", key);
+ } else {
+ printf("Couldn't recover key.\n");
}
- free(s);
- return 0;
+ printf("Time spent: %1.2f seconds\n", (float)(msclock() - start_time)/1000.0);
}
-#include <inttypes.h>
-#include "crapto1/crapto1.h"
#include <stdio.h>
#include <string.h>
+#include <inttypes.h>
+#include "crapto1/crapto1.h"
+#include "util.h"
-int main (int argc, char *argv[]) {
- struct Crypto1State *revstate;
- uint64_t key; // recovered key
- uint32_t uid; // serial number
- uint32_t nt; // tag challenge
- uint32_t nr_enc; // encrypted reader challenge
- uint32_t ar_enc; // encrypted reader response
- uint32_t at_enc; // encrypted tag response
- uint32_t ks2; // keystream used to encrypt reader response
- uint32_t ks3; // keystream used to encrypt tag response
-
- printf("MIFARE Classic key recovery - based 64 bits of keystream\n");
- printf("Recover key from only one complete authentication!\n\n");
+int main (int argc, char *argv[])
+{
+ uint32_t uid; // serial numDber
+ uint32_t nt; // tag challenge
+ uint32_t nr_enc; // encrypted reader challenge
+ uint32_t ar_enc; // encrypted reader response
+ uint32_t at_enc; // encrypted tag response
+ uint64_t key = 0; // recovered key
+ struct Crypto1State *revstate;
+ uint32_t ks2; // keystream used to encrypt reader response
+ uint32_t ks3; // keystream used to encrypt tag response
- if (argc < 6 ) {
- printf(" syntax: %s <uid> <nt> <{nr}> <{ar}> <{at}> [enc] [enc...]\n\n", argv[0]);
- return 1;
- }
+ printf("MIFARE Classic key recovery - based on 64 bits of keystream\n");
+ printf("Recover key from only one complete authentication!\n\n");
- int encc = argc - 6;
- int enclen[encc];
- uint8_t enc[encc][120];
+ if (argc < 6 ) {
+ printf(" syntax: %s <uid> <nt> <{nr}> <{ar}> <{at}> [enc] [enc...]\n\n", argv[0]);
+ return 1;
+ }
- sscanf(argv[1], "%x", &uid);
- sscanf(argv[2], "%x", &nt);
- sscanf(argv[3], "%x", &nr_enc);
- sscanf(argv[4], "%x", &ar_enc);
- sscanf(argv[5], "%x", &at_enc);
- for (int i = 0; i < encc; i++) {
- enclen[i] = strlen(argv[i + 6]) / 2;
- for (int i2 = 0; i2 < enclen[i]; i2++) {
- sscanf(argv[i+6] + i2*2,"%2x", (unsigned int *)&enc[i][i2]);
- }
- }
- printf("Recovering key for:\n");
+ int encc = argc - 6;
+ int enclen[encc];
+ uint8_t enc[encc][120];
- printf(" uid: %08x\n", uid);
- printf(" nt: %08x\n", nt);
- printf(" {nr}: %08x\n", nr_enc);
- printf(" {ar}: %08x\n", ar_enc);
- printf(" {at}: %08x\n", at_enc);
- for (int i = 0; i < encc; i++) {
- printf("{enc%d}: ", i);
- for (int i2 = 0; i2 < enclen[i]; i2++) {
- printf("%02x", enc[i][i2]);
- }
- printf("\n");
- }
+ sscanf(argv[1], "%x", &uid);
+ sscanf(argv[2], "%x", &nt);
+ sscanf(argv[3], "%x", &nr_enc);
+ sscanf(argv[4], "%x", &ar_enc);
+ sscanf(argv[5], "%x", &at_enc);
+ for (int i = 0; i < encc; i++) {
+ enclen[i] = strlen(argv[i + 6]) / 2;
+ for (int i2 = 0; i2 < enclen[i]; i2++) {
+ sscanf(argv[i+6] + i2*2,"%2x", (unsigned int*)&enc[i][i2]);
+ }
+ }
+ printf("Recovering key for:\n");
+ printf(" uid: %08x\n", uid);
+ printf(" nt: %08x\n", nt);
+ printf(" {nr}: %08x\n", nr_enc);
+ printf(" {ar}: %08x\n", ar_enc);
+ printf(" {at}: %08x\n", at_enc);
+ for (int i = 0; i < encc; i++) {
+ printf("{enc%d}: ", i);
+ for (int i2 = 0; i2 < enclen[i]; i2++) {
+ printf("%02x", enc[i][i2]);
+ }
+ printf("\n");
+ }
- /*
- uint32_t uid = 0x9c599b32;
- uint32_t tag_challenge = 0x82a4166c;
- uint32_t nr_enc = 0xa1e458ce;
- uint32_t reader_response = 0x6eea41e0;
- uint32_t tag_response = 0x5cadf439;
-*/
- // Generate lfsr succesors of the tag challenge
- printf("\nLFSR succesors of the tag challenge:\n");
- printf(" nt': %08x\n",prng_successor(nt, 64));
- printf(" nt'': %08x\n",prng_successor(nt, 96));
+ printf("\nLFSR successors of the tag challenge:\n");
+ printf(" nt' : %08x\n",prng_successor(nt, 64));
+ printf(" nt'': %08x\n",prng_successor(nt, 96));
- // Extract the keystream from the messages
- printf("\nKeystream used to generate {ar} and {at}:\n");
- ks2 = ar_enc ^ prng_successor(nt, 64);
- ks3 = at_enc ^ prng_successor(nt, 96);
- printf(" ks2: %08x\n",ks2);
- printf(" ks3: %08x\n",ks3);
+ // Extract the keystream from the messages
+ ks2 = ar_enc ^ prng_successor(nt, 64);
+ ks3 = at_enc ^ prng_successor(nt, 96);
+
+ uint64_t start_time = msclock();
+ revstate = lfsr_recovery64(ks2, ks3);
+ uint64_t time_spent = msclock() - start_time;
+ printf("Time spent in lfsr_recovery64(): %1.2f seconds\n", (float)time_spent/1000.0);
+ printf("\nKeystream used to generate {ar} and {at}:\n");
+ printf(" ks2: %08x\n",ks2);
+ printf(" ks3: %08x\n",ks3);
- revstate = lfsr_recovery64(ks2, ks3);
+ // Decrypting communication using keystream if presented
+ if (argc > 6 ) {
+ printf("\nDecrypted communication:\n");
+ uint8_t ks4;
+ int rollb = 0;
+ for (int i = 0; i < encc; i++) {
+ printf("{dec%d}: ", i);
+ for (int i2 = 0; i2 < enclen[i]; i2++) {
+ ks4 = crypto1_byte(revstate, 0, 0);
+ printf("%02x", ks4 ^ enc[i][i2]);
+ rollb += 1;
+ }
+ printf("\n");
+ }
+ for (int i = 0; i < rollb; i++) {
+ lfsr_rollback_byte(revstate, 0, 0);
+ }
+ }
- // Decrypting communication using keystream if presented
- if (argc > 6 ) {
- printf("\nDecrypted communication:\n");
- uint8_t ks4;
- int rollb = 0;
- for (int i = 0; i < encc; i++) {
- printf("{dec%d}: ", i);
- for (int i2 = 0; i2 < enclen[i]; i2++) {
- ks4 = crypto1_byte(revstate, 0, 0);
- printf("%02x", ks4 ^ enc[i][i2]);
- rollb += 1;
- }
- printf("\n");
- }
- for (int i = 0; i < rollb; i++) {
- lfsr_rollback_byte(revstate, 0, 0);
- }
- }
-
- lfsr_rollback_word(revstate, 0, 0);
- lfsr_rollback_word(revstate, 0, 0);
- lfsr_rollback_word(revstate, nr_enc, 1);
- lfsr_rollback_word(revstate, uid ^ nt, 0);
- crypto1_get_lfsr(revstate, &key);
- printf("\nFound Key: [%012" PRIx64"]\n\n",key);
- crypto1_destroy(revstate);
+ lfsr_rollback_word(revstate, 0, 0);
+ lfsr_rollback_word(revstate, 0, 0);
+ lfsr_rollback_word(revstate, nr_enc, 1);
+ lfsr_rollback_word(revstate, uid ^ nt, 0);
+ crypto1_get_lfsr(revstate, &key);
+ crypto1_destroy(revstate);
- return 0;
+ printf("\nFound Key: [%012" PRIx64"]\n\n",key);
+
}