set_tracing(TRUE);\r
\r
for (i = 0; i < keyCount; ++i) {\r
- if (mifare_classic_halt(pcs, cuid))\r
- if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error");\r
\r
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {\r
if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card");\r
}\r
\r
ui64Key = bytes_to_num(datain + i * 6, 6);\r
- if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST))\r
+ if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
+ if (mifare_classic_halt(pcs, cuid))\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error");\r
continue;\r
+ }\r
\r
isOK = 1;\r
break;\r
}\r
- crypto1_destroy(pcs);\r
\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6);\r
+\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
set_tracing(FALSE);\r
+ crypto1_destroy(pcs);\r
\r
// restore debug level\r
MF_DBGLEVEL = OLD_MF_DBGLEVEL; \r
// variables\r
int len; \r
uint32_t pos;\r
- uint8_t tmp4[4] = {0x00};\r
uint8_t par[1] = {0x00};\r
\r
// "random" reader nonce:\r
- byte_t nr[4] = {0x55, 0x41, 0x49, 0x92};\r
- //byte_t nr[4] = {0x01, 0x01, 0x01, 0x01};\r
+ //byte_t nr[4] = {0x55, 0x41, 0x49, 0x92};\r
+ byte_t nr[4] = {0x01, 0x01, 0x01, 0x01};\r
\r
uint32_t nt, ntpp; // Supplied tag nonce\r
\r
return 2;\r
}\r
\r
- memcpy(tmp4, receivedAnswer, 4);\r
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0);\r
- \r
- if (ntpp != bytes_to_num(tmp4, 4)) {\r
+\r
+ if (ntpp != bytes_to_num(receivedAnswer, 4)) {\r
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Error card response.");\r
return 3;\r
}\r
#include "mifarehost.h"\r
#include "proxmark3.h"\r
//#include "radixsort.h"\r
+#include <time.h>\r
\r
// MIFARE\r
int compar_int(const void * a, const void * b) {\r
//return (*(uint64_t*)b - *(uint64_t*)a);\r
\r
// better:\r
- /*if (*(uint64_t*)b < *(uint64_t*)a) return -1;\r
if (*(uint64_t*)b > *(uint64_t*)a) return 1;\r
+ if (*(uint64_t*)b < *(uint64_t*)a) return -1; \r
return 0;\r
-*/\r
- return (*(uint64_t*)b > *(uint64_t*)a) - (*(uint64_t*)b < *(uint64_t*)a);\r
+\r
+ //return (*(uint64_t*)b > *(uint64_t*)a) - (*(uint64_t*)b < *(uint64_t*)a);\r
}\r
\r
// Compare 16 Bits out of cryptostate\r
int Compare16Bits(const void * a, const void * b) {\r
-\r
-/*\r
- if ((*(uint64_t*)b & 0x00ff000000ff0000) < (*(uint64_t*)a & 0x00ff000000ff0000)) return -1;\r
if ((*(uint64_t*)b & 0x00ff000000ff0000) > (*(uint64_t*)a & 0x00ff000000ff0000)) return 1; \r
+ if ((*(uint64_t*)b & 0x00ff000000ff0000) < (*(uint64_t*)a & 0x00ff000000ff0000)) return -1;\r
return 0;\r
-*/\r
- return \r
+\r
+/* return \r
((*(uint64_t*)b & 0x00ff000000ff0000) > (*(uint64_t*)a & 0x00ff000000ff0000))\r
-\r
((*(uint64_t*)b & 0x00ff000000ff0000) < (*(uint64_t*)a & 0x00ff000000ff0000))\r
;\r
+*/\r
}\r
\r
typedef \r
// wrapper function for multi-threaded lfsr_recovery32\r
void* nested_worker_thread(void *arg)\r
{\r
+ clock_t t1 = clock();\r
struct Crypto1State *p1;\r
StateList_t *statelist = arg;\r
\r
statelist->tail.sltail = --p1;\r
qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits);\r
\r
+ \r
+ t1 = clock() - t1;\r
+ printf("lfsr_recovery32 takes %.0f ticks \n", (float)t1);\r
return statelist->head.slhead;\r
}\r
\r
while (Compare16Bits(p1, p2) == 1) p2++;\r
}\r
}\r
- \r
+\r
p3->even = 0; p3->odd = 0;\r
p4->even = 0; p4->odd = 0;\r
statelists[0].len = p3 - statelists[0].head.slhead;\r
// intersection of both lists. Create the intersection:\r
qsort(statelists[0].head.keyhead, statelists[0].len, sizeof(uint64_t), compar_int);\r
qsort(statelists[1].head.keyhead, statelists[1].len, sizeof(uint64_t), compar_int);\r
-\r
+ \r
uint64_t *p5, *p6, *p7;\r
p5 = p7 = statelists[0].head.keyhead; \r
p6 = statelists[1].head.keyhead;\r
+ \r
while (p5 <= statelists[0].tail.keytail && p6 <= statelists[1].tail.keytail) {\r
if (compar_int(p5, p6) == 0) {\r
*p7++ = *p5++;\r
statelists[0].len = p7 - statelists[0].head.keyhead;\r
statelists[0].tail.keytail = --p7;\r
\r
+ uint32_t numOfCandidates = statelists[0].len;\r
+ if ( numOfCandidates == 0 ) goto out;\r
+ \r
memset(resultKey, 0, 6);\r
uint64_t key64 = 0;\r
\r
// The list may still contain several key candidates. Test each of them with mfCheckKeys\r
// uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt;\r
+ uint8_t keyBlock[USB_CMD_DATA_SIZE] = {0x00};\r
\r
- uint32_t numOfCandidates = statelists[0].len;\r
- if ( numOfCandidates > 0 ) {\r
-\r
- uint8_t keyBlock[USB_CMD_DATA_SIZE] = {0x00};\r
+ clock_t t1 = clock();\r
+ for (i = 0; i < numOfCandidates; ++i){\r
+ crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);\r
+ num_to_bytes(key64, 6, keyBlock + i * 6);\r
+ }\r
\r
- for (i = 0; i < numOfCandidates; ++i){\r
- crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);\r
- num_to_bytes(key64, 6, keyBlock + i * 6);\r
- }\r
+ if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, numOfCandidates, keyBlock, &key64)) { \r
+ free(statelists[0].head.slhead);\r
+ free(statelists[1].head.slhead);\r
+ num_to_bytes(key64, 6, resultKey);\r
\r
- if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, numOfCandidates, keyBlock, &key64)) { \r
- free(statelists[0].head.slhead);\r
- free(statelists[1].head.slhead);\r
- num_to_bytes(key64, 6, resultKey);\r
-\r
- PrintAndLog("UID: %08x target block:%3u key type: %c -- Found key [%012"llx"]",\r
- uid,\r
- (uint16_t)resp.arg[2] & 0xff,\r
- (resp.arg[2] >> 8) ? 'B' : 'A',\r
- key64\r
- );\r
- return -5;\r
- }\r
+ t1 = clock() - t1;\r
+ printf("Check candidates takes %.0f ticks \n", (float)t1); \r
\r
+ PrintAndLog("UID: %08x target block:%3u key type: %c -- Found key [%012"llx"]",\r
+ uid,\r
+ (uint16_t)resp.arg[2] & 0xff,\r
+ (resp.arg[2] >> 8) ? 'B' : 'A',\r
+ key64\r
+ );\r
+ return -5;\r
}\r
+ \r
+out:\r
PrintAndLog("UID: %08x target block:%3u key type: %c",\r
uid,\r
(uint16_t)resp.arg[2] & 0xff,\r
{\r
uint32_t i;\r
for(i = 0; i < 1 << 20; ++i)\r
- filterlut[i] = filter(i);\r
+ filterlut[i] = filter(i);\r
}\r
#define filter(x) (filterlut[(x) & 0xfffff])\r
#endif\r
return statelist;\r
}\r
\r
-static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214,\r
+static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214,\r
0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83,\r
0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA};\r
static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60,\r
if(!s || !odd || !even) {\r
free(statelist);\r
statelist = 0;\r
- goto out;\r
+ goto out;\r
}\r
\r
for(o = odd; *o + 1; ++o)\r
}\r
}\r
\r
-/** binsearch\r
- * Binary search for the first occurence of *stop's MSB in sorted [start,stop]\r
- */\r
-static inline uint32_t* binsearch(uint32_t *start, uint32_t *stop)\r
-{\r
- uint32_t mid, val = *stop & 0xff000000;\r
- while(start != stop)\r
- if(start[mid = (stop - start) >> 1] > val)\r
- stop = &start[mid];\r
- else\r
- start += mid + 1;\r
-\r
- return start;\r
-}\r
\r
/** update_contribution\r
* helper, calculates the partial linear feedback contributions and puts in MSB\r
*/\r
-static inline void\r
-update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)\r
+static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)\r
{\r
uint32_t p = *item >> 25;\r
\r
/** extend_table\r
* using a bit of the keystream extend the table of possible lfsr states\r
*/\r
-static inline void\r
-extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)\r
+static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)\r
{\r
in <<= 24;\r
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)\r
*/\r
static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit)\r
{\r
- for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)\r
+ for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) {\r
if(filter(*tbl) ^ filter(*tbl | 1)) { // replace\r
*tbl |= filter(*tbl) ^ bit;\r
} else if(filter(*tbl) == bit) { // insert\r
*++*end = *++tbl;\r
*tbl = tbl[-1] | 1;\r
- } else // drop\r
+ } else { // drop\r
*tbl-- = *(*end)--;\r
+ }\r
+ }\r
}\r
/** recover\r
* recursively narrow down the search space, 4 bits of keystream at a time\r
oks >>= 1;\r
eks >>= 1;\r
in >>= 2;\r
- extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1,\r
- LF_POLY_ODD << 1, 0);\r
+ extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0);\r
if(o_head > o_tail)\r
return sl;\r
\r
- extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD,\r
- LF_POLY_EVEN << 1 | 1, in & 3);\r
+ extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3);\r
if(e_head > e_tail)\r
return sl;\r
}\r
\r
// allocate memory for out of place bucket_sort\r
bucket_array_t bucket;\r
- for (uint32_t i = 0; i < 2; i++)\r
+ \r
+ for (uint32_t i = 0; i < 2; i++) {\r
for (uint32_t j = 0; j <= 0xff; j++) {\r
bucket[i][j].head = malloc(sizeof(uint32_t)<<14);\r
if (!bucket[i][j].head) {\r
goto out;\r
}\r
}\r
-\r
+ }\r
\r
// initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream\r
for(i = 1 << 20; i >= 0; --i) {\r
// 22 bits to go to recover 32 bits in total. From now on, we need to take the "in"\r
// parameter into account.\r
in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping\r
- recover(odd_head, odd_tail, oks,\r
- even_head, even_tail, eks, 11, statelist, in << 1, bucket);\r
-\r
+ recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket);\r
\r
out:\r
- free(odd_head);\r
- free(even_head);\r
for (uint32_t i = 0; i < 2; i++)\r
for (uint32_t j = 0; j <= 0xff; j++)\r
free(bucket[i][j].head);\r
-\r
+ free(odd_head);\r
+ free(even_head);\r
return statelist;\r
}\r
\r
odd = lfsr_prefix_ks(ks, 1);\r
even = lfsr_prefix_ks(ks, 0);\r
\r
- s = statelist = malloc((sizeof *statelist) << 21);\r
+ s = statelist = malloc((sizeof *statelist) << 20);\r
if(!s || !odd || !even) {\r
free(statelist);\r
- free(odd);\r
- free(even);\r
- return 0;\r
+ statelist = 0;\r
+ goto out;\r
}\r
\r
for(o = odd; *o + 1; ++o)\r
}\r
\r
s->odd = s->even = 0;\r
-\r
+out:\r
free(odd);\r
free(even);\r
return statelist;\r
-}
\ No newline at end of file
+}\r
Copyright (C) 2008-2014 bla <blapost@gmail.com>
*/
-#ifndef CRAPTO1_INCLUDED
-#define CRAPTO1_INCLUDED
+#ifndef CRAPTO1_H__
+#define CRAPTO1_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
struct Crypto1State * crypto1_create(uint64_t key)
{
struct Crypto1State *s = malloc(sizeof(*s));
+ if ( !s ) return NULL;
+
s->odd = s->even = 0;
+
int i;
-
- for(i = 47;s && i > 0; i -= 2) {
+ //for(i = 47;s && i > 0; i -= 2) {
+ for(i = 47; i > 0; i -= 2) {
s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7);
s->even = s->even << 1 | BIT(key, i ^ 7);
}
+ 1287: : a1 e4 58 ce 6e ea 41 e0
+ 64: 0: TAG 5c ad f4 39
-./mfkey64 9c599b32 82a4166c a1e458ce 6eea41e0 5cadf439
+:: Sample values
+:: <uid> <nt> <nr_0> <ar_0> <nr_1> <ar_1>
+./mfkey32 52B0F519 5417D1F8 4D545EA7 E15AC8C2 dac1a7f4 5ae5c37f
+
+:: <uid> <nt> <nr_0> <ar_0> <nt1> <nr_1> <ar_1>
+./mfkey32v2 12345678 1AD8DF2B 1D316024 620EF048 30D6CB07 C52077E2 837AC61A
+./mfkey32v2 52B0F519 5417D1F8 4D545EA7 E15AC8C2 A1BA88C6 DAC1A7F4 5AE5C37F
+
+:: <uid> <nt> <nr> <ar> <at>
+./mfkey64 9C599B32 82A4166C A1E458CE 6EEA41E0 5CADF439
+./mfkey64 52B0F519 5417D1F8 4D545EA7 E15AC8C2 5056e41b
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-#define llx PRIx64
-#define lli PRIi64
-
-// Test-file: test2.c
#include "crapto1.h"
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
+#define llx PRIx64
+#define lli PRIi64
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
- uint32_t ks2; // keystream used to encrypt reader response
+ 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
+ uint32_t ks2; // keystream used to encrypt reader response
- printf("MIFARE Classic key recovery - based 32 bits of keystream\n");
- printf("Recover key from two 32-bit reader authentication answers only!\n\n");
+ printf("MIFARE Classic key recovery - based 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]);
- return 1;
- }
+ if (argc < 7) {
+ printf(" syntax: %s <uid> <nt> <nr_0> <ar_0> <nr_1> <ar_1>\n\n",argv[0]);
+ 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);
+ 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);
- 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("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);
// 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 succesors 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 = ar0_enc ^ prng_successor(nt, 64);
- printf(" ks2: %08x\n",ks2);
+ clock_t t1 = clock();
+
+ // Extract the keystream from the messages
+ printf("\nKeystream used to generate {ar} and {at}:\n");
+ ks2 = ar0_enc ^ prng_successor(nt, 64);
+ printf(" ks2: %08x\n",ks2);
s = lfsr_recovery32(ar0_enc ^ prng_successor(nt, 64), 0);
printf("\nFound Key: [%012"llx"]\n\n",key);
break;}
}
- free(s);
-
- return 0;
+ free(s);
+ t1 = clock() - t1;
+ if ( t1 > 0 ) printf("Time : %.0f ticks \n", (float)t1);
+ return 0;
}
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-#define llx PRIx64
-#define lli PRIi64
-
-// Test-file: test2.c
#include "crapto1.h"
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
+#define llx PRIx64
+#define lli PRIi64
int main (int argc, char *argv[]) {
struct Crypto1State *s,*t;
uint64_t key; // recovered key
uint32_t ks2; // keystream used to encrypt reader response
printf("MIFARE Classic key recovery - based 32 bits of keystream VERSION2\n");
- printf("Recover key from two 32-bit reader authentication answers only");
+ printf("Recover key from two 32-bit reader authentication answers only\n");
printf("This version implements Moebius two different nonce solution (like the supercard)\n\n");
if (argc < 8) {
- printf(" syntax: %s <uid> <nt> <{nr_0}> <{ar_0}> <nt1> <{nr_1}> <{ar_1}>\n\n",argv[0]);
+ printf("syntax: %s <uid> <nt> <nr_0> <ar_0> <nt1> <nr_1> <ar_1>\n\n", argv[0]);
return 1;
}
printf("\nLFSR succesors of the tag challenge:\n");
printf(" nt': %08x\n",prng_successor(nt0, 64));
printf(" nt'': %08x\n",prng_successor(nt0, 96));
+ clock_t t1 = clock();
// Extract the keystream from the messages
printf("\nKeystream used to generate {ar} and {at}:\n");
break;}
}
free(s);
-
+ t1 = clock() - t1;
+ if ( t1 > 0 ) printf("Time : %.0f ticks \n", (float)t1 );
return 0;
}
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
-#define llx PRIx64
-#define lli PRIi64
-
-// Test-file: test2.c
#include "crapto1.h"
#include <stdio.h>
+#include <time.h>
+
+#define llx PRIx64
+#define lli PRIi64
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
+ 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");
+ printf("MIFARE Classic key recovery - based 64 bits of keystream\n");
+ printf("Recover key from only one complete authentication!\n\n");
- if (argc < 6) {
- printf(" syntax: %s <uid> <nt> <{nr}> <{ar}> <{at}>\n\n",argv[0]);
- return 1;
- }
+ if (argc < 6) {
+ printf(" syntax: %s <uid> <nt> <nr> <ar> <at>\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);
+ 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);
- 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);
+ 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);
-/*
- 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));
-
- // 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);
-
- revstate = lfsr_recovery64(ks2, ks3);
- 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"llx"]\n\n",key);
- crypto1_destroy(revstate);
+ printf("\nLFSR succesors of the tag challenge:\n");
+ printf(" nt': %08x\n",prng_successor(nt, 64));
+ printf(" nt'': %08x\n",prng_successor(nt, 96));
+
+ clock_t t1 = clock();
+
+ // 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);
- return 0;
+ revstate = lfsr_recovery64(ks2, ks3);
+ 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"llx"]\n\n",key);
+ crypto1_destroy(revstate);
+
+ t1 = clock() - t1;
+ if ( t1 > 0 ) printf("Time : %.0f ticks \n", (float)t1);
+ return 0;
}
CC = gcc
LD = gcc
-CFLAGS = -Wall -O3 -c
+CFLAGS = -std=c99 -Wall -O3 -c
LDFLAGS =
OBJS = crypto1.o crapto1.o
}\r
}\r
\r
-/** binsearch\r
- * Binary search for the first occurence of *stop's MSB in sorted [start,stop]\r
- */\r
-static inline uint32_t* binsearch(uint32_t *start, uint32_t *stop)\r
-{\r
- uint32_t mid, val = *stop & 0xff000000;\r
- while(start != stop)\r
- if(start[mid = (stop - start) >> 1] > val)\r
- stop = &start[mid];\r
- else\r
- start += mid + 1;\r
-\r
- return start;\r
-}\r
-\r
/** update_contribution\r
* helper, calculates the partial linear feedback contributions and puts in MSB\r
*/\r
-static inline void\r
-update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)\r
+static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)\r
{\r
uint32_t p = *item >> 25;\r
\r
/** extend_table\r
* using a bit of the keystream extend the table of possible lfsr states\r
*/\r
-static inline void\r
-extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)\r
+static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)\r
{\r
in <<= 24;\r
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)\r
*/\r
static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit)\r
{\r
- for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)\r
+ for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) {\r
if(filter(*tbl) ^ filter(*tbl | 1)) { // replace\r
*tbl |= filter(*tbl) ^ bit;\r
} else if(filter(*tbl) == bit) { // insert\r
*++*end = *++tbl;\r
*tbl = tbl[-1] | 1;\r
- } else // drop\r
+ } else { // drop\r
*tbl-- = *(*end)--;\r
+ }\r
+ }\r
}\r
/** recover\r
* recursively narrow down the search space, 4 bits of keystream at a time\r
oks >>= 1;\r
eks >>= 1;\r
in >>= 2;\r
- extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1,\r
- LF_POLY_ODD << 1, 0);\r
+ extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0);\r
if(o_head > o_tail)\r
return sl;\r
\r
- extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD,\r
- LF_POLY_EVEN << 1 | 1, in & 3);\r
+ extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3);\r
if(e_head > e_tail)\r
return sl;\r
}\r
\r
// allocate memory for out of place bucket_sort\r
bucket_array_t bucket;\r
- for (uint32_t i = 0; i < 2; i++)\r
+ \r
+ for (uint32_t i = 0; i < 2; i++) {\r
for (uint32_t j = 0; j <= 0xff; j++) {\r
bucket[i][j].head = malloc(sizeof(uint32_t)<<14);\r
if (!bucket[i][j].head) {\r
goto out;\r
}\r
}\r
-\r
+ }\r
\r
// initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream\r
for(i = 1 << 20; i >= 0; --i) {\r
// 22 bits to go to recover 32 bits in total. From now on, we need to take the "in"\r
// parameter into account.\r
in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping\r
- recover(odd_head, odd_tail, oks,\r
- even_head, even_tail, eks, 11, statelist, in << 1, bucket);\r
-\r
+ recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket);\r
\r
out:\r
- free(odd_head);\r
- free(even_head);\r
for (uint32_t i = 0; i < 2; i++)\r
for (uint32_t j = 0; j <= 0xff; j++)\r
free(bucket[i][j].head);\r
-\r
+ free(odd_head);\r
+ free(even_head);\r
return statelist;\r
}\r
\r
odd = lfsr_prefix_ks(ks, 1);\r
even = lfsr_prefix_ks(ks, 0);\r
\r
- s = statelist = malloc((sizeof *statelist) << 21);\r
+ s = statelist = malloc((sizeof *statelist) << 20);\r
if(!s || !odd || !even) {\r
free(statelist);\r
- free(odd);\r
- free(even);\r
- return 0;\r
+ statelist = 0;\r
+ goto out;\r
}\r
\r
for(o = odd; *o + 1; ++o)\r
}\r
\r
s->odd = s->even = 0;\r
-\r
+out:\r
free(odd);\r
free(even);\r
return statelist;\r
-}
\ No newline at end of file
+}\r
Copyright (C) 2008-2014 bla <blapost@gmail.com>
*/
-#ifndef CRAPTO1_INCLUDED
-#define CRAPTO1_INCLUDED
+#ifndef CRAPTO1_H__
+#define CRAPTO1_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
struct Crypto1State * crypto1_create(uint64_t key)
{
struct Crypto1State *s = malloc(sizeof(*s));
+ if ( !s ) return NULL;
+
s->odd = s->even = 0;
+
int i;
-
- for(i = 47;s && i > 0; i -= 2) {
+ //for(i = 47;s && i > 0; i -= 2) {
+ for(i = 47; i > 0; i -= 2) {
s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7);
s->even = s->even << 1 | BIT(key, i ^ 7);
}
#include <inttypes.h>
#define llx PRIx64
#include <stdio.h>
+#include <time.h>
typedef unsigned char byte_t;
int main(const int argc, const char* argv[]) {
- struct Crypto1State *state;
- uint32_t pos, uid, nt, nr, rr, nr_diff, ks1, ks2;
- byte_t bt, i, ks3x[8], par[8][8];
- uint64_t key, key_recovered;
- uint64_t par_info;
- uint64_t ks_info;
- nr = rr = 0;
-
- if (argc < 5) {
- printf("\nsyntax: %s <uid> <nt> <par> <ks>\n\n",argv[0]);
- return 1;
- }
- sscanf(argv[1],"%08x",&uid);
- sscanf(argv[2],"%08x",&nt);
- sscanf(argv[3],"%016"llx,&par_info);
- sscanf(argv[4],"%016"llx,&ks_info);
-
- // Reset the last three significant bits of the reader nonce
- nr &= 0xffffff1f;
+ struct Crypto1State *state;
+ uint32_t pos, uid, nt, nr, rr, nr_diff, ks1, ks2;
+ byte_t bt, i, ks3x[8], par[8][8];
+ uint64_t key, key_recovered;
+ uint64_t par_info;
+ uint64_t ks_info;
+ nr = rr = 0;
+
+ if (argc < 5) {
+ printf("\nsyntax: %s <uid> <nt> <par> <ks>\n\n",argv[0]);
+ return 1;
+ }
+ sscanf(argv[1],"%08x",&uid);
+ sscanf(argv[2],"%08x",&nt);
+ sscanf(argv[3],"%016"llx,&par_info);
+ sscanf(argv[4],"%016"llx,&ks_info);
- printf("\nuid(%08x) nt(%08x) par(%016"llx") ks(%016"llx")\n\n",uid,nt,par_info,ks_info);
-
- for (pos=0; pos<8; pos++)
- {
- ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
- bt = (par_info >> (pos*8)) & 0xff;
- for (i=0; i<8; i++)
- {
- par[7-pos][i] = (bt >> i) & 0x01;
- }
- }
-
- printf("|diff|{nr} |ks3|ks3^5|parity |\n");
- printf("+----+--------+---+-----+---------------+\n");
- for (i=0; i<8; i++)
- {
- nr_diff = nr | i << 5;
- printf("| %02x |%08x|",i << 5, nr_diff);
- printf(" %01x | %01x |",ks3x[i], ks3x[i]^5);
- for (pos=0; pos<7; pos++) printf("%01x,",par[i][pos]);
- printf("%01x|\n",par[i][7]);
- }
+ // Reset the last three significant bits of the reader nonce
+ nr &= 0xffffff1f;
+
+ printf("\nuid(%08x) nt(%08x) par(%016"llx") ks(%016"llx")\n\n",uid,nt,par_info,ks_info);
+
+ for ( pos = 0; pos < 8; pos++ ) {
+ ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
+ bt = (par_info >> (pos*8)) & 0xff;
+
+ for ( i = 0; i < 8; i++) {
+ par[7-pos][i] = (bt >> i) & 0x01;
+ }
+ }
+
+ printf("|diff|{nr} |ks3|ks3^5|parity |\n");
+ printf("+----+--------+---+-----+---------------+\n");
+
+ for ( i = 0; i < 8; i++) {
+ nr_diff = nr | i << 5;
+ printf("| %02x |%08x| %01x | %01x |", i << 5, nr_diff, ks3x[i], ks3x[i]^5);
+
+ for ( pos = 0; pos < 7; pos++)
+ printf("%01x,", par[i][pos]);
+ printf("%01x|\n", par[i][7]);
+ }
+ printf("+----+--------+---+-----+---------------+\n");
+
+ clock_t t1 = clock();
- state = lfsr_common_prefix(nr,rr,ks3x,par);
- lfsr_rollback_word(state,uid^nt,0);
- crypto1_get_lfsr(state,&key_recovered);
- printf("\nkey recovered: %012"llx"\n\n",key_recovered);
- crypto1_destroy(state);
+ state = lfsr_common_prefix(nr,rr,ks3x,par);
+ lfsr_rollback_word(state,uid^nt,0);
+ crypto1_get_lfsr(state,&key_recovered);
+ printf("\nkey recovered: %012"llx"\n\n",key_recovered);
+ crypto1_destroy(state);
- return 0;
+ t1 = clock() - t1;
+ if ( t1 > 0 ) printf("Time in nonce2key: %.0f ticks \n", (float)t1);
+ return 0;
}