fix to darkside overdue. I needed to remove my old impl..

This commit is contained in:
iceman1001 2017-12-06 17:15:24 +01:00
commit 1f637d726f
17 changed files with 385 additions and 1598 deletions

View file

@ -12,9 +12,6 @@ TARFLAGS = -C .. --ignore-failed-read -rvf
RM = rm -f
MV = mv
# uncomment to enable EMV
#CFLAGS += -DWITH_EMV
ENV_LDFLAGS := $(LDFLAGS)
ENV_CFLAGS := $(CFLAGS)
@ -90,7 +87,6 @@ CORESRCS = uart_posix.c \
util_posix.c \
scandir.c
CMDSRCS = crapto1/crapto1.c \
crapto1/crypto1.c \
mfkey.c \
@ -210,15 +206,7 @@ MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_AVX2.o)
#GCC_GTEQ_490 := $(shell expr `gcc --version | awk '/gcc/{print $$NF;}' | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/'` \>= 40900)
GCC_VERSION := $(shell gcc --version | awk '/gcc/{print $$NF;}' | sed -e 's/\-.*//g' -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/')
CLANG_VERSION := $(shell gcc --version | awk '/Apple LLVM version/{print $$4;}' | sed -e 's/\-.*//g' -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/')
ifneq ($(CLANG_VERSION), )
SUPPORTS_AVX512 := $(shell [ $(CLANG_VERSION) -ge 80000 ] && echo "True" )
endif
ifneq ($(GCC_VERSION), )
SUPPORTS_AVX512 := $(shell [ $(GCC_VERSION) -ge 40900 ] && echo "True" )
endif
SUPPORTS_AVX512 := $(shell echo | gcc -E -mavx512f - > /dev/null 2>&1 && echo "True" )
HARD_SWITCH_NOSIMD = -mno-mmx -mno-sse2 -mno-avx -mno-avx2
HARD_SWITCH_MMX = -mmmx -mno-sse2 -mno-avx -mno-avx2

View file

@ -152,15 +152,17 @@ static uint16_t calcSumNibbleXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
}
static uint16_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) {
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++)
for (uint8_t i = 0; i < len; i++) {
sum ^= bytes[i];
}
sum &= mask;
return sum;
}
static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) {
uint16_t sum = 0;
for (uint8_t i = 0; i < len; i++)
for (uint8_t i = 0; i < len; i++) {
sum += bytes[i];
}
sum &= mask;
return sum;
}
@ -171,8 +173,9 @@ static uint16_t calcSumByteAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask)
static uint16_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) {
uint8_t sum = 0;
for (uint8_t i = 0; i < len; i++)
for (uint8_t i = 0; i < len; i++) {
sum -= bytes[i];
}
sum &= mask;
return sum;
}
@ -414,35 +417,179 @@ int CmdAnalyseTEASelfTest(const char *Cmd){
}
int CmdAnalyseA(const char *Cmd){
/*
piwi
//piwi
// uid(2e086b1a) nt(230736f6) ks(0b0008000804000e) nr(000000000)
// uid(2e086b1a) nt(230736f6) ks(0e0b0e0b090c0d02) nr(000000001)
// uid(2e086b1a) nt(230736f6) ks(0e05060e01080b08) nr(000000002)
uint64_t d1[] = {0x2e086b1a, 0x230736f6, 0x0000001, 0x0e0b0e0b090c0d02};
uint64_t d2[] = {0x2e086b1a, 0x230736f6, 0x0000002, 0x0e05060e01080b08};
//uint64_t d1[] = {0x2e086b1a, 0x230736f6, 0x0000001, 0x0e0b0e0b090c0d02};
//uint64_t d2[] = {0x2e086b1a, 0x230736f6, 0x0000002, 0x0e05060e01080b08};
// uid(17758822) nt(c0c69e59) ks(080105020705040e) nr(00000001)
// uid(17758822) nt(c0c69e59) ks(01070a05050c0705) nr(00000002)
uint64_t d1[] = {0x17758822, 0xc0c69e59, 0x0000001, 0x080105020705040e};
uint64_t d2[] = {0x17758822, 0xc0c69e59, 0x0000002, 0x01070a05050c0705};
//uint64_t d1[] = {0x17758822, 0xc0c69e59, 0x0000001, 0x080105020705040e};
//uint64_t d2[] = {0x17758822, 0xc0c69e59, 0x0000002, 0x01070a05050c0705};
// uid(6e442129) nt(8f699195) ks(090d0b0305020f02) nr(00000001)
// uid(6e442129) nt(8f699195) ks(03030508030b0c0e) nr(00000002)
// uid(6e442129) nt(8f699195) ks(02010f030c0d050d) nr(00000003)
// uid(6e442129) nt(8f699195) ks(00040f0f0305030e) nr(00000004)
uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02};
uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e};
//uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02};
//uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e};
/*
uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001)
uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002)
*/
// uint64_t key = 0;
// uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0x0c0e0f0505080800};
// uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0x0e06090d03000b0f};
uint64_t *keylistA = NULL, *keylistB = NULL;
uint32_t keycountA = 0, keycountB = 0;
// uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800};
// uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f};
uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02};
uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e};
// nonce2key_ex(0, 0 , d1[0], d1[1], d1[2], d1[3], &key);
// nonce2key_ex(0, 0 , d2[0], d2[1], d2[2], d2[3], &key);
keycountA = nonce2key(d1[0], d1[1], d1[2], d1[3], d1[4] ,&keylistA);
keycountB = nonce2key(d2[0], d2[1], d2[2], d2[3], d2[4], &keylistB);
switch (keycountA) {
case 0: printf("Key test A failed\n"); break;
case 1: printf("KEY A | %012" PRIX64 " ", keylistA[0]); break;
}
switch (keycountB) {
case 0: printf("Key test B failed\n"); break;
case 1: printf("KEY B | %012" PRIX64 " ", keylistB[0]); break;
}
free(keylistA);
free(keylistB);
// qsort(keylist, keycount, sizeof(*keylist), compare_uint64);
// keycount = intersection(last_keylist, keylist);
/*
uint64_t keys[] = {
0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961,
0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3,
0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c,
0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9,
0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a,
0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba,
0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b,
0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe
};
uint64_t keya[] = {
0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961,
0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3,
0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c,
0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9
};
uint64_t keyb[] = {
0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a,
0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba,
0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b,
0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe
};
*/
/*
uint64_t xor[] = {
0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B,
0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6,
0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52,
0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC, 0xB6E97F5F6776,
0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F,
0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD,
0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8,
0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244
};
uint64_t xorA[] = {
0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B,
0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6,
0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52,
0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC
};
uint64_t xorB[] = {
0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F,
0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD,
0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8,
0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244
};
*/
/*
// xor key A | xor key B
1 | 0DEFED88E531 | 2F87A1BDC230
2 | 7577AFA2E1BC | E43F502B984C
3 | 14D7D7BDBEC3 | 8A776AB752D9
4 | F5ABD3C6278B | 9A58D96A472F
5 | AABDFA08276F | EF3702E01916
6 | B77C275C10D6 | 48A03B01D007
7 | B6DD0B434080 | 14754B0D659E
8 | AAF2444499C6 | 009AD1868FDD
9 | 852D7F8EBF90 | 6082DB527C11
10 | 3108821DB92C | 4D666ADA4C0E
11 | B3756A1FB685 | 2D461D05F163
12 | DFE627C86A52 | 3596CFF0FEC8
13 | 5D3C093EF375 | 8CBD9258FE22
14 | 28C81D6FBF0E | 00D29A7B304B
15 | 1204DF4D3ECC | BC33DC6C9244
*/
// generate xor table :)
/*
for (uint8_t i=0; i<31; i++){
uint64_t a = keys[i] ^ keys[i+1];
printf("%u | %012" PRIX64 " | \n", i, a);
}
*/
/*
uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16);
uint8_t uid[6] = {0};
num_to_bytes(id,4,uid);
uint8_t key_s0a[] = {
uid[1] ^ uid[2] ^ uid[3] ^ 0x11,
uid[1] ^ 0x72,
uid[2] ^ 0x80,
(uid[0] + uid[1] + uid[2] + uid[3] ) ^ uid[3] ^ 0x19,
0xA3,
0x2F
};
printf("UID | %s\n", sprint_hex(uid,4 ));
printf("KEY A | %s\n", sprint_hex(key_s0a, 6));
// arrays w all keys
uint64_t foo[32] = {0};
//A
foo[0] = bytes_to_num(key_s0a, 6);
//B
//foo[16] = 0xcafe71411fbf;
foo[16] = 0xeafe51411fbf;
for (uint8_t i=0; i<15; i++){
foo[i+1] = foo[i] ^ xorA[i];
foo[i+16+1] = foo[i+16] ^ xorB[i];
}
for (uint8_t i=0; i<15; i++){
uint64_t a = foo[i];
uint64_t b = foo[i+16];
printf("%02u | %012" PRIX64 " %s | %012" PRIX64 " %s\n",
i,
a,
( a == keya[i])?"ok":"err",
b,
( b == keyb[i])?"ok":"err"
);
}
*/
return 0;
}

View file

@ -23,6 +23,7 @@
#include "tea.h"
#include "legic_prng.h"
#include "loclass/elite_crack.h"
#include "mfkey.h" //nonce2key
int usage_analyse_lcr(void);
int usage_analyse_checksum(void);

View file

@ -10,7 +10,83 @@
// MIFARE Darkside hack
//-----------------------------------------------------------------------------
#include "mfkey.h"
#include "crapto1/crapto1.h"
// MIFARE
int compare_uint64(const void *a, const void *b) {
if (*(uint64_t*)b == *(uint64_t*)a) return 0;
if (*(uint64_t*)b < *(uint64_t*)a) return 1;
return -1;
}
// create the intersection (common members) of two sorted lists. Lists are terminated by -1. Result will be in list1. Number of elements is returned.
uint32_t intersection(uint64_t *listA, uint64_t *listB) {
if (listA == NULL || listB == NULL)
return 0;
uint64_t *p1, *p2, *p3;
p1 = p3 = listA;
p2 = listB;
while ( *p1 != -1 && *p2 != -1 ) {
if (compare_uint64(p1, p2) == 0) {
*p3++ = *p1++;
p2++;
}
else {
while (compare_uint64(p1, p2) == -1) ++p1;
while (compare_uint64(p1, p2) == 1) ++p2;
}
}
*p3 = -1;
return p3 - listA;
}
// Darkside attack (hf mf mifare)
// if successful it will return a list of keys, not just one.
uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys) {
struct Crypto1State *states;
uint32_t i, pos, rr = 0;
uint8_t bt, ks3x[8], par[8][8];
uint64_t key_recovered;
static uint64_t *keylist;
// Reset the last three significant bits of the reader nonce
nr &= 0xFFFFFF1F;
for ( pos = 0; pos < 8; pos++ ) {
ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0F;
bt = (par_info >> (pos*8)) & 0xFF;
par[7-pos][0] = (bt >> 0) & 1;
par[7-pos][1] = (bt >> 1) & 1;
par[7-pos][2] = (bt >> 2) & 1;
par[7-pos][3] = (bt >> 3) & 1;
par[7-pos][4] = (bt >> 4) & 1;
par[7-pos][5] = (bt >> 5) & 1;
par[7-pos][6] = (bt >> 6) & 1;
par[7-pos][7] = (bt >> 7) & 1;
}
states = lfsr_common_prefix(nr, rr, ks3x, par, (par_info == 0));
if (!states) {
printf("Failed getting states\n");
*keys = NULL;
return 0;
}
keylist = (uint64_t*)states;
for (i = 0; keylist[i]; i++) {
lfsr_rollback_word(states+i, uid^nt, 0);
crypto1_get_lfsr(states+i, &key_recovered);
keylist[i] = key_recovered;
}
keylist[i] = -1;
*keys = keylist;
return i;
}
// recover key from 2 different reader responses on same tag challenge
bool mfkey32(nonces_t data, uint64_t *outputkey) {
@ -20,7 +96,9 @@ bool mfkey32(nonces_t data, uint64_t *outputkey) {
bool isSuccess = false;
uint8_t counter = 0;
s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
uint32_t p640 = prng_successor(data.nonce, 64);
uint32_t p641 = prng_successor(data.nonce2, 64);
s = lfsr_recovery32(data.ar ^ p640, 0);
for(t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
@ -29,7 +107,7 @@ bool mfkey32(nonces_t data, uint64_t *outputkey) {
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))) {
if (data.ar2 == (crypto1_word(t, 0, 0) ^ p641)) {
outkey = key;
counter++;
if (counter == 20) break;
@ -42,14 +120,17 @@ bool mfkey32(nonces_t data, uint64_t *outputkey) {
}
// recover key from 2 reader responses on 2 different tag challenges
// skip "several found keys". Only return true if ONE key is found
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;
uint32_t p640 = prng_successor(data.nonce, 64);
uint32_t p641 = prng_successor(data.nonce2, 64);
s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0);
s = lfsr_recovery32(data.ar ^ p640, 0);
for(t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
@ -59,11 +140,10 @@ bool mfkey32_moebius(nonces_t data, uint64_t *outputkey) {
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))) {
outkey=key;
if (data.ar2 == (crypto1_word(t, 0, 0) ^ p641)) {
outkey = key;
++counter;
if (counter==20)
break;
if (counter == 20) break;
}
}
isSuccess = (counter == 1);
@ -92,5 +172,3 @@ int mfkey64(nonces_t data, uint64_t *outputkey){
*outputkey = key;
return 0;
}

View file

@ -13,12 +13,18 @@
#ifndef MFKEY_H
#define MFKEY_H
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "mifare.h"
#include "crapto1/crapto1.h"
extern uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys);
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);
extern int compare_uint64(const void *a, const void *b);
extern uint32_t intersection(uint64_t *listA, uint64_t *listB);
#endif

View file

@ -9,78 +9,6 @@
//-----------------------------------------------------------------------------
#include "mifarehost.h"
// MIFARE
static int compare_uint64(const void *a, const void *b) {
if (*(uint64_t*)b == *(uint64_t*)a) return 0;
if (*(uint64_t*)b < *(uint64_t*)a) return 1;
return -1;
}
// create the intersection (common members) of two sorted lists. Lists are terminated by -1. Result will be in list1. Number of elements is returned.
static uint32_t intersection(uint64_t *list1, uint64_t *list2) {
if (list1 == NULL || list2 == NULL)
return 0;
uint64_t *p1, *p2, *p3;
p1 = p3 = list1;
p2 = list2;
while ( *p1 != -1 && *p2 != -1 ) {
if (compare_uint64(p1, p2) == 0) {
*p3++ = *p1++;
p2++;
}
else {
while (compare_uint64(p1, p2) == -1) ++p1;
while (compare_uint64(p1, p2) == 1) ++p2;
}
}
*p3 = -1;
return p3 - list1;
}
// Darkside attack (hf mf mifare)
// if successful it will return a list of keys, not just one.
static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys) {
struct Crypto1State *states;
uint32_t i, pos, rr;
uint8_t bt, ks3x[8], par[8][8];
uint64_t key_recovered;
static uint64_t *keylist;
rr = 0;
// Reset the last three significant bits of the reader nonce
nr &= 0xffffff1f;
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;
}
}
states = lfsr_common_prefix(nr, rr, ks3x, par, (par_info == 0));
if (!states) {
PrintAndLog("Failed getting states");
*keys = NULL;
return 0;
}
keylist = (uint64_t*)states;
for (i = 0; keylist[i]; i++) {
lfsr_rollback_word(states+i, uid^nt, 0);
crypto1_get_lfsr(states+i, &key_recovered);
keylist[i] = key_recovered;
}
keylist[i] = -1;
*keys = keylist;
return i;
}
int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
uint32_t uid = 0;
uint32_t nt = 0, nr = 0;
@ -97,7 +25,6 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
printf("Press pm3-button on the proxmark3 device to abort both proxmark3 and client.\n");
printf("-------------------------------------------------------------------------\n");
while (true) {
clearCommandBuffer();
SendCommand(&c);
@ -118,7 +45,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) {
}
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
isOK = resp.arg[0];
if (isOK < 0)
return isOK;
@ -869,6 +796,9 @@ int detect_classic_nackbug(bool verbose){
if ( verbose )
printf("Press pm3-button on the proxmark3 device to abort both proxmark3 and client.\n");
// for nice animation
//bool stdinOnPipe = !isatty(STDIN_FILENO)
while (true) {
printf(".");

View file

@ -26,6 +26,7 @@
#include "iso14443crc.h"
#include "protocols.h"
#include "mifare.h"
#include "mfkey.h"
#define NESTED_SECTOR_RETRY 10

View file

@ -1,567 +0,0 @@
/* crapto1.c
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, US$
Copyright (C) 2008-2014 bla <blapost@gmail.com>
*/
#include "crapto1.h"
#include <stdlib.h>
#include <stdio.h>
#if !defined LOWMEM && defined __GNUC__
static uint8_t filterlut[1 << 20];
static void __attribute__((constructor)) fill_lut()
{
uint32_t i;
for(i = 0; i < 1 << 20; ++i)
filterlut[i] = filter(i);
}
#define filter(x) (filterlut[(x) & 0xfffff])
#endif
/** update_contribution
* helper, calculates the partial linear feedback contributions and puts in MSB
*/
static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2)
{
uint32_t p = *item >> 25;
p = p << 1 | parity(*item & mask1);
p = p << 1 | parity(*item & mask2);
*item = p << 24 | (*item & 0xffffff);
}
/** extend_table
* using a bit of the keystream extend the table of possible lfsr states
*/
static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in)
{
in <<= 24;
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1)
if(filter(*tbl) ^ filter(*tbl | 1)) {
*tbl |= filter(*tbl) ^ bit;
update_contribution(tbl, m1, m2);
*tbl ^= in;
} else if(filter(*tbl) == bit) {
*++*end = tbl[1];
tbl[1] = tbl[0] | 1;
update_contribution(tbl, m1, m2);
*tbl++ ^= in;
update_contribution(tbl, m1, m2);
*tbl ^= in;
} else
*tbl-- = *(*end)--;
}
/** extend_table_simple
* using a bit of the keystream extend the table of possible lfsr states
*/
static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit)
{
for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) {
if(filter(*tbl) ^ filter(*tbl | 1)) { // replace
*tbl |= filter(*tbl) ^ bit;
} else if(filter(*tbl) == bit) { // insert
*++*end = *++tbl;
*tbl = tbl[-1] | 1;
} else { // drop
*tbl-- = *(*end)--;
}
}
}
/** recover
* recursively narrow down the search space, 4 bits of keystream at a time
*/
static struct Crypto1State*
recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem,
struct Crypto1State *sl, uint32_t in, bucket_array_t bucket)
{
uint32_t *o, *e;
bucket_info_t bucket_info;
if(rem == -1) {
for(e = e_head; e <= e_tail; ++e) {
*e = *e << 1 ^ parity(*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[1].odd = sl[1].even = 0;
}
}
return sl;
}
for(uint32_t i = 0; i < 4 && rem--; i++) {
oks >>= 1;
eks >>= 1;
in >>= 2;
extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0);
if(o_head > o_tail)
return sl;
extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3);
if(e_head > e_tail)
return sl;
}
bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket);
for (int i = bucket_info.numbuckets - 1; i >= 0; i--) {
sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks,
bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks,
rem, sl, in, bucket);
}
return sl;
}
/** lfsr_recovery
* recover the state of the lfsr given 32 bits of the keystream
* additionally you can use the in parameter to specify the value
* that was fed into the lfsr at the time the keystream was generated
*/
struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in)
{
struct Crypto1State *statelist;
uint32_t *odd_head = 0, *odd_tail = 0, oks = 0;
uint32_t *even_head = 0, *even_tail = 0, eks = 0;
int i;
// split the keystream into an odd and even part
for(i = 31; i >= 0; i -= 2)
oks = oks << 1 | BEBIT(ks2, i);
for(i = 30; i >= 0; i -= 2)
eks = eks << 1 | BEBIT(ks2, i);
odd_head = odd_tail = malloc(sizeof(uint32_t) << 21);
even_head = even_tail = malloc(sizeof(uint32_t) << 21);
statelist = malloc(sizeof(struct Crypto1State) << 18);
if(!odd_tail-- || !even_tail-- || !statelist) {
free(statelist);
statelist = 0;
goto out;
}
statelist->odd = statelist->even = 0;
// allocate memory for out of place bucket_sort
bucket_array_t bucket;
for (uint32_t i = 0; i < 2; i++) {
for (uint32_t j = 0; j <= 0xff; j++) {
bucket[i][j].head = malloc(sizeof(uint32_t)<<14);
if (!bucket[i][j].head) {
goto out;
}
}
}
// initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream
for(i = 1 << 20; i >= 0; --i) {
if(filter(i) == (oks & 1))
*++odd_tail = i;
if(filter(i) == (eks & 1))
*++even_tail = i;
}
// extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even):
for(i = 0; i < 4; i++) {
extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1);
extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1);
}
// the statelists now contain all states which could have generated the last 10 Bits of the keystream.
// 22 bits to go to recover 32 bits in total. From now on, we need to take the "in"
// parameter into account.
in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping
recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket);
out:
for (uint32_t i = 0; i < 2; i++)
for (uint32_t j = 0; j <= 0xff; j++)
free(bucket[i][j].head);
free(odd_head);
free(even_head);
return statelist;
}
static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214,
0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83,
0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA};
static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60,
0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8,
0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20,
0x7EC7EE90, 0x7F63F748, 0x79117020};
static const uint32_t T1[] = {
0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66,
0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B,
0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615,
0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C};
static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0,
0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268,
0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0,
0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0,
0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950,
0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0};
static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD};
static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0};
/** Reverse 64 bits of keystream into possible cipher states
* Variation mentioned in the paper. Somewhat optimized version
*/
struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3)
{
struct Crypto1State *statelist, *sl;
uint8_t oks[32], eks[32], hi[32];
uint32_t low = 0, win = 0;
uint32_t *tail, table[1 << 16];
int i, j;
sl = statelist = malloc(sizeof(struct Crypto1State) << 4);
if(!sl)
return 0;
sl->odd = sl->even = 0;
for(i = 30; i >= 0; i -= 2) {
oks[i >> 1] = BEBIT(ks2, i);
oks[16 + (i >> 1)] = BEBIT(ks3, i);
}
for(i = 31; i >= 0; i -= 2) {
eks[i >> 1] = BEBIT(ks2, i);
eks[16 + (i >> 1)] = BEBIT(ks3, i);
}
for(i = 0xfffff; i >= 0; --i) {
if (filter(i) != oks[0])
continue;
*(tail = table) = i;
for(j = 1; tail >= table && j < 29; ++j)
extend_table_simple(table, &tail, oks[j]);
if(tail < table)
continue;
for(j = 0; j < 19; ++j)
low = low << 1 | parity(i & S1[j]);
for(j = 0; j < 32; ++j)
hi[j] = parity(i & T1[j]);
for(; tail >= table; --tail) {
for(j = 0; j < 3; ++j) {
*tail = *tail << 1;
*tail |= parity((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 ^= low;
for(j = 0; j < 32; ++j) {
win = win << 1 ^ hi[j] ^ parity(*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);
sl->even = win;
++sl;
sl->odd = sl->even = 0;
continue2:;
}
}
return statelist;
}
/** lfsr_rollback_bit
* Rollback the shift register in order to get previous states
*/
uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb)
{
int out;
uint8_t ret;
uint32_t t;
s->odd &= 0xffffff;
t = s->odd, s->odd = s->even, s->even = t;
out = s->even & 1;
out ^= LF_POLY_EVEN & (s->even >>= 1);
out ^= LF_POLY_ODD & s->odd;
out ^= !!in;
out ^= (ret = filter(s->odd)) & !!fb;
s->even |= parity(out) << 23;
return ret;
}
/** lfsr_rollback_byte
* Rollback the shift register in order to get previous states
*/
uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb)
{
/*
int i, ret = 0;
for (i = 7; i >= 0; --i)
ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i;
*/
// unfold loop 20160112
uint8_t ret = 0;
ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7;
ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6;
ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5;
ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4;
ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3;
ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2;
ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1;
ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0;
return ret;
}
/** lfsr_rollback_word
* Rollback the shift register in order to get previous states
*/
uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb)
{
/*
int i;
uint32_t ret = 0;
for (i = 31; i >= 0; --i)
ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24);
*/
// unfold loop 20160112
uint32_t ret = 0;
ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24);
return ret;
}
/** nonce_distance
* x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y
*/
static uint16_t *dist = 0;
int nonce_distance(uint32_t from, uint32_t to)
{
uint16_t x, i;
if(!dist) {
dist = malloc(2 << 16);
if(!dist)
return -1;
for (x = i = 1; i; ++i) {
dist[(x & 0xff) << 8 | x >> 8] = i;
x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
}
}
return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535;
}
/** validate_prng_nonce
* Determine if nonce is deterministic. ie: Suspectable to Darkside attack.
* returns
* true = weak prng
* false = hardend prng
*/
bool validate_prng_nonce(uint32_t nonce) {
// init prng table:
nonce_distance(nonce, nonce);
return ((65535 - dist[nonce >> 16] + dist[nonce & 0xffff]) % 65535) == 16;
}
static uint32_t fastfwd[2][8] = {
{ 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB},
{ 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}};
/** lfsr_prefix_ks
*
* Is an exported helper function from the common prefix attack
* Described in the "dark side" paper. It returns an -1 terminated array
* of possible partial(21 bit) secret state.
* The required keystream(ks) needs to contain the keystream that was used to
* encrypt the NACK which is observed when varying only the 3 last bits of Nr
* only correct iff [NR_3] ^ NR_3 does not depend on Nr_3
*/
uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
{
uint32_t *candidates = malloc(4 << 10);
if(!candidates) return 0;
uint32_t c, entry;
int size = 0, i, good;
for(i = 0; i < 1 << 21; ++i) {
for(c = 0, good = 1; good && c < 8; ++c) {
entry = i ^ fastfwd[isodd][c];
good &= (BIT(ks[c], isodd) == filter(entry >> 1));
good &= (BIT(ks[c], isodd + 2) == filter(entry));
}
if(good)
candidates[size++] = i;
}
candidates[size] = -1;
return candidates;
}
/** check_pfx_parity
* helper function which eliminates possible secret states using parity bits
*/
static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl)
{
uint32_t ks1, nr, ks2, rr, ks3, c, good = 1;
for(c = 0; good && c < 8; ++c) {
sl->odd = odd ^ fastfwd[1][c];
sl->even = even ^ fastfwd[0][c];
lfsr_rollback_bit(sl, 0, 0);
lfsr_rollback_bit(sl, 0, 0);
ks3 = lfsr_rollback_bit(sl, 0, 0);
ks2 = lfsr_rollback_word(sl, 0, 0);
ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1);
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;
}
return sl + good;
}
static struct Crypto1State* check_pfx_parity_ex(uint32_t prefix, uint32_t odd, uint32_t even, struct Crypto1State* sl) {
uint32_t c = 0;
sl->odd = odd ^ fastfwd[1][c];
sl->even = even ^ fastfwd[0][c];
lfsr_rollback_bit(sl, 0, 0);
lfsr_rollback_bit(sl, 0, 0);
lfsr_rollback_bit(sl, 0, 0);
lfsr_rollback_word(sl, 0, 0);
lfsr_rollback_word(sl, prefix | c << 5, 1);
return ++sl;
}
/** lfsr_common_prefix
* Implentation of the common prefix attack.
* Requires the 28 bit constant prefix used as reader nonce (pfx)
* The reader response used (rr)
* The keystream used to encrypt the observed NACK's (ks)
* The parity bits (par)
* It returns a zero terminated list of possible cipher states after the
* tag nonce was fed in
*/
struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8])
{
struct Crypto1State *statelist, *s;
uint32_t *odd, *even, *o, *e, top;
odd = lfsr_prefix_ks(ks, 1);
even = lfsr_prefix_ks(ks, 0);
s = statelist = malloc((sizeof *statelist) << 24);
if(!s || !odd || !even) {
free(statelist);
statelist = 0;
goto out;
}
for(o = odd; *o + 1; ++o)
for(e = even; *e + 1; ++e)
for(top = 0; top < 64; ++top) {
*o += 1 << 21;
*e += (!(top & 7) + 1) << 21;
s = check_pfx_parity(pfx, rr, par, *o, *e, s);
}
s->odd = s->even = 0;
out:
free(odd);
free(even);
return statelist;
}
struct Crypto1State* lfsr_common_prefix_ex(uint32_t pfx, uint8_t ks[8])
{
struct Crypto1State *statelist, *s;
uint32_t *odd, *even, *o, *e, top;
odd = lfsr_prefix_ks(ks, 1);
even = lfsr_prefix_ks(ks, 0);
s = statelist = malloc((sizeof *statelist) << 24);
if(!s || !odd || !even) {
free(statelist);
statelist = 0;
goto out;
}
for(o = odd; *o + 1; ++o)
for(e = even; *e + 1; ++e)
for(top = 0; top < 64; ++top) {
*o += 1 << 21;
*e += (!(top & 7) + 1) << 21;
s = check_pfx_parity_ex(pfx, *o, *e, s);
}
// in this version, -1 signifies end of states
s->odd = s->even = -1;
out:
free(odd);
free(even);
return statelist;
}

View file

@ -1,103 +0,0 @@
/* crapto1.h
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, US$
Copyright (C) 2008-2014 bla <blapost@gmail.com>
*/
#ifndef CRAPTO1_H__
#define CRAPTO1_H__
#include <stdint.h>
#include <stdbool.h>
#include "bucketsort.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Crypto1State {uint32_t odd, even;};
struct Crypto1State* crypto1_create(uint64_t);
void crypto1_destroy(struct Crypto1State*);
void crypto1_get_lfsr(struct Crypto1State*, uint64_t*);
uint8_t crypto1_bit(struct Crypto1State*, uint8_t, int);
uint8_t crypto1_byte(struct Crypto1State*, uint8_t, int);
uint32_t crypto1_word(struct Crypto1State*, uint32_t, int);
uint32_t prng_successor(uint32_t x, uint32_t n);
struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in);
struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3);
uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd);
struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]);
// douvan's no-parity function
struct Crypto1State* lfsr_common_prefix_ex(uint32_t pfx, uint8_t ks[8]);
uint8_t lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb);
uint8_t lfsr_rollback_byte(struct Crypto1State* s, uint32_t in, int fb);
uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb);
int nonce_distance(uint32_t from, uint32_t to);
extern bool validate_prng_nonce(uint32_t nonce);
#define SWAPENDIAN(x)\
(x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16)
#define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\
uint32_t __n = 0,__M = 0, N = 0;\
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))\
break;\
else if(__i)\
__M = prng_successor(__M, (__i == 7) ? 48 : 8);\
else
#define LF_POLY_ODD (0x29CE5C)
#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;
f = 0xf22c0 >> (x & 0xf) & 16;
f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8;
f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4;
f |= 0x1e458 >> (x >> 12 & 0xf) & 2;
f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
return BIT(0xEC57E80A, f);
}
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,146 +0,0 @@
/* crypto1.c
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, US
Copyright (C) 2008-2008 bla <blapost@gmail.com>
*/
#include "crapto1.h"
#include <stdlib.h>
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; i > 0; i -= 2) {
s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7);
s->even = s->even << 1 | BIT(key, i ^ 7);
}
return s;
}
void crypto1_destroy(struct Crypto1State *state)
{
free(state);
}
void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr)
{
int i;
for(*lfsr = 0, i = 23; i >= 0; --i) {
*lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3);
*lfsr = *lfsr << 1 | BIT(state->even, i ^ 3);
}
}
uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted)
{
uint32_t feedin;
uint32_t tmp;
uint8_t ret = filter(s->odd);
feedin = ret & !!is_encrypted;
feedin ^= !!in;
feedin ^= LF_POLY_ODD & s->odd;
feedin ^= LF_POLY_EVEN & s->even;
s->even = s->even << 1 | parity(feedin);
tmp = s->odd;
s->odd = s->even;
s->even = tmp;
return ret;
}
uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted)
{
/*
uint8_t i, ret = 0;
for (i = 0; i < 8; ++i)
ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i;
*/
// unfold loop 20161012
uint8_t ret = 0;
ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0;
ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1;
ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2;
ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3;
ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4;
ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5;
ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6;
ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7;
return ret;
}
uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted)
{
/*
uint32_t i, ret = 0;
for (i = 0; i < 32; ++i)
ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24);
*/
//unfold loop 2016012
uint32_t ret = 0;
ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24);
return ret;
}
/* prng_successor
* helper used to obscure the keystream during authentication
*/
uint32_t prng_successor(uint32_t x, uint32_t n)
{
SWAPENDIAN(x);
while(n--)
x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
return SWAPENDIAN(x);
}

View file

@ -1,120 +0,0 @@
// Bit-sliced Crypto-1 implementation
// The cipher states are stored with the least significant bit first, hence all bit indexes are reversed here
/*
Copyright (c) 2015-2016 Aram Verstegen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "crypto1_bs.h"
#include <inttypes.h>
#define __STDC_FORMAT_MACROS
// The following functions use this global or thread-local state
// It is sized to fit exactly KEYSTREAM_SIZE more states next to the initial state
__thread bitslice_t states[KEYSTREAM_SIZE+STATE_SIZE];
__thread bitslice_t * restrict state_p;
void crypto1_bs_init(){
// initialize constant one and zero bit vectors
memset(bs_ones.bytes, 0xff, VECTOR_SIZE);
memset(bs_zeroes.bytes, 0x00, VECTOR_SIZE);
}
// The following functions have side effects on 48 bitslices at the state_p pointer
// use the crypto1_bs_rewind_* macros to (re-)initialize them as needed
inline const bitslice_value_t crypto1_bs_bit(const bitslice_value_t input, const bool is_encrypted){
bitslice_value_t feedback = (state_p[47- 0].value ^ state_p[47- 5].value ^ state_p[47- 9].value ^
state_p[47-10].value ^ state_p[47-12].value ^ state_p[47-14].value ^
state_p[47-15].value ^ state_p[47-17].value ^ state_p[47-19].value ^
state_p[47-24].value ^ state_p[47-25].value ^ state_p[47-27].value ^
state_p[47-29].value ^ state_p[47-35].value ^ state_p[47-39].value ^
state_p[47-41].value ^ state_p[47-42].value ^ state_p[47-43].value);
const bitslice_value_t ks_bits = crypto1_bs_f20(state_p);
if(is_encrypted){
feedback ^= ks_bits;
}
state_p--;
state_p[0].value = feedback ^ input;
return ks_bits;
}
inline const bitslice_value_t crypto1_bs_lfsr_rollback(const bitslice_value_t input, const bool is_encrypted){
bitslice_value_t feedout = state_p[0].value;
state_p++;
const bitslice_value_t ks_bits = crypto1_bs_f20(state_p);
if(is_encrypted){
feedout ^= ks_bits;
}
const bitslice_value_t feedback = (feedout ^ state_p[47- 5].value ^ state_p[47- 9].value ^
state_p[47-10].value ^ state_p[47-12].value ^ state_p[47-14].value ^
state_p[47-15].value ^ state_p[47-17].value ^ state_p[47-19].value ^
state_p[47-24].value ^ state_p[47-25].value ^ state_p[47-27].value ^
state_p[47-29].value ^ state_p[47-35].value ^ state_p[47-39].value ^
state_p[47-41].value ^ state_p[47-42].value ^ state_p[47-43].value);
state_p[47].value = feedback ^ input;
return ks_bits;
}
// side-effect free from here on
// note that bytes are sliced and unsliced with reversed endianness
inline void crypto1_bs_convert_states(bitslice_t bitsliced_states[], state_t regular_states[]){
size_t bit_idx = 0, slice_idx = 0;
state_t values[MAX_BITSLICES];
memset(values, 0x0, sizeof(values));
for(slice_idx = 0; slice_idx < MAX_BITSLICES; slice_idx++){
for(bit_idx = 0; bit_idx < STATE_SIZE; bit_idx++){
bool bit = get_vector_bit(slice_idx, bitsliced_states[bit_idx]);
values[slice_idx].value <<= 1;
values[slice_idx].value |= bit;
}
// swap endianness
values[slice_idx].value = rev_state_t(values[slice_idx].value);
// roll off unused bits
//values[slice_idx].value >>= ((sizeof(state_t)*8)-STATE_SIZE); // - 48
values[slice_idx].value >>= 16;
}
memcpy(regular_states, values, sizeof(values));
}
// bitslice a value
void crypto1_bs_bitslice_value32(uint32_t value, bitslice_t bitsliced_value[], size_t bit_len){
// load nonce bytes with unswapped endianness
size_t bit_idx;
for(bit_idx = 0; bit_idx < bit_len; bit_idx++){
bool bit = get_bit(bit_len-1-bit_idx, rev32(value));
if(bit){
bitsliced_value[bit_idx].value = bs_ones.value;
} else {
bitsliced_value[bit_idx].value = bs_zeroes.value;
}
}
}
void crypto1_bs_print_states(bitslice_t bitsliced_states[]){
size_t slice_idx = 0;
state_t values[MAX_BITSLICES] = {{0x00}};
crypto1_bs_convert_states(bitsliced_states, values);
for(slice_idx = 0; slice_idx < MAX_BITSLICES; slice_idx++){
printf("State %03zu: %012" PRIx64 "\n", slice_idx, values[slice_idx].value);
}
}

View file

@ -1,99 +0,0 @@
#ifndef _CRYPTO1_BS_H
#define _CRYPTO1_BS_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
// bitslice type
// while AVX supports 256 bit vector floating point operations, we need integer operations for boolean logic
// same for AVX2 and 512 bit vectors
// using larger vectors works but seems to generate more register pressure
#if defined(__AVX2__)
#define MAX_BITSLICES 256
#elif defined(__AVX__)
#define MAX_BITSLICES 128
#elif defined(__SSE2__)
#define MAX_BITSLICES 128
#else
#define MAX_BITSLICES 64
#endif
#define VECTOR_SIZE (MAX_BITSLICES/8)
typedef unsigned int __attribute__((aligned(VECTOR_SIZE))) __attribute__((vector_size(VECTOR_SIZE))) bitslice_value_t;
typedef union {
bitslice_value_t value;
uint64_t bytes64[MAX_BITSLICES/64];
uint8_t bytes[MAX_BITSLICES/8];
} bitslice_t;
// filter function (f20)
// sourced from ``Wirelessly Pickpocketing a Mifare Classic Card'' by Flavio Garcia, Peter van Rossum, Roel Verdult and Ronny Wichers Schreur
#define f20a(a,b,c,d) (((a|b)^(a&d))^(c&((a^b)|d)))
#define f20b(a,b,c,d) (((a&b)|c)^((a^b)&(c|d)))
#define f20c(a,b,c,d,e) ((a|((b|e)&(d^e)))^((a^(b&d))&((c^d)|(b&e))))
#define crypto1_bs_f20(s) \
f20c(f20a((s[47- 9].value), (s[47-11].value), (s[47-13].value), (s[47-15].value)), \
f20b((s[47-17].value), (s[47-19].value), (s[47-21].value), (s[47-23].value)), \
f20b((s[47-25].value), (s[47-27].value), (s[47-29].value), (s[47-31].value)), \
f20a((s[47-33].value), (s[47-35].value), (s[47-37].value), (s[47-39].value)), \
f20b((s[47-41].value), (s[47-43].value), (s[47-45].value), (s[47-47].value)))
// bit indexing
#define get_bit(n, word) ((word >> (n)) & 1)
#define get_vector_bit(slice, value) get_bit(slice&0x3f, value.bytes64[slice>>6])
// constant ones/zeroes
bitslice_t bs_ones;
bitslice_t bs_zeroes;
// size of crypto-1 state
#define STATE_SIZE 48
// size of nonce to be decrypted
#define KEYSTREAM_SIZE 32
// size of first uid^nonce byte to be rolled back to the initial key
#define ROLLBACK_SIZE 8
// number of nonces required to test to cover entire 48-bit state
// I would have said it's 12... but bla goes with 100, so I do too
#define NONCE_TESTS 100
// state pointer management
extern __thread bitslice_t states[KEYSTREAM_SIZE+STATE_SIZE];
extern __thread bitslice_t * restrict state_p;
// rewind to the point a0, at which KEYSTREAM_SIZE more bits can be generated
#define crypto1_bs_rewind_a0() (state_p = &states[KEYSTREAM_SIZE])
// bitsliced bytewise parity
#define bitsliced_byte_parity(n) (n[0].value ^ n[1].value ^ n[2].value ^ n[3].value ^ n[4].value ^ n[5].value ^ n[6].value ^ n[7].value)
// 48-bit crypto-1 states are normally represented using 64-bit values
typedef union {
uint64_t value;
uint8_t bytes[8];
} state_t;
// endianness conversion
#define rev32(word) (((word & 0xff) << 24) | (((word >> 8) & 0xff) << 16) | (((word >> 16) & 0xff) << 8) | (((word >> 24) & 0xff)))
#define rev64(x) (rev32(x)<<32|(rev32((x>>32))))
#define rev_state_t rev64
// crypto-1 functions
const bitslice_value_t crypto1_bs_bit(const bitslice_value_t input, const bool is_encrypted);
const bitslice_value_t crypto1_bs_lfsr_rollback(const bitslice_value_t input, const bool is_encrypted);
// initialization functions
void crypto1_bs_init();
// conversion functions
void crypto1_bs_bitslice_value32(uint32_t value, bitslice_t bitsliced_value[], size_t bit_len);
void crypto1_bs_convert_states(bitslice_t bitsliced_states[], state_t regular_states[]);
// debug print
void crypto1_bs_print_states(bitslice_t *bitsliced_states);
#endif // _CRYPTO1_BS_H

View file

@ -1,335 +0,0 @@
//-----------------------------------------------------------------------------
// 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"
// called with a uint8_t *x array
#define LE32TOH(x) (uint32_t)( ( (x)[3]<<24) | ( (x)[2]<<16) | ( (x)[1]<<8) | (x)[0]);
int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key) {
struct Crypto1State *state;
uint32_t i, pos, rr = 0, nr_diff;
byte_t bt, ks3x[8], par[8][8];
// Reset the last three significant bits of the reader nonce
nr &= 0xffffff1f;
PrintAndLog("uid(%08x) nt(%08x) par(%016" PRIx64") ks(%016" PRIx64") nr(%08x)", uid, nt, par_info, ks_info, nr);
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;
}
}
PrintAndLog("+----+--------+---+-----+---------------+");
PrintAndLog("|diff|{nr} |ks3|ks3^5|parity |");
PrintAndLog("+----+--------+---+-----+---------------+");
for ( i = 0; i < 8; i++) {
nr_diff = nr | i << 5;
PrintAndLog("| %02x |%08x| %01x | %01x |%01x,%01x,%01x,%01x,%01x,%01x,%01x,%01x|",
i << 5, nr_diff, ks3x[i], ks3x[i]^5,
par[i][0], par[i][1], par[i][2], par[i][3],
par[i][4], par[i][5], par[i][6], par[i][7]);
}
PrintAndLog("+----+--------+---+-----+---------------+");
uint64_t t1 = msclock();
state = lfsr_common_prefix(nr, rr, ks3x, par);
lfsr_rollback_word(state, uid ^ nt, 0);
crypto1_get_lfsr(state, key);
crypto1_destroy(state);
t1 = msclock() - t1;
PrintAndLog("Time in nonce2key: %.0f ticks", (float)t1/1000.0);
return 0;
}
int compar_intA(const void * a, const void * b) {
if (*(int64_t*)b == *(int64_t*)a) return 0;
if (*(int64_t*)b > *(int64_t*)a) return 1;
return -1;
}
// call when PAR == 0, special attack? It seems to need two calls. with same uid, block, keytype
int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint64_t * key) {
struct Crypto1State *state;
uint32_t i, pos, key_count;
uint8_t ks3x[8];
uint64_t key_recovered;
int64_t *state_s;
static uint8_t last_blockno;
static uint8_t last_keytype;
static uint32_t last_uid;
static int64_t *last_keylist;
if (last_uid != uid &&
last_blockno != blockno &&
last_keytype != keytype &&
last_keylist != NULL)
{
free(last_keylist);
last_keylist = NULL;
}
last_uid = uid;
last_blockno = blockno;
last_keytype = keytype;
// Reset the last three significant bits of the reader nonce
nr &= 0xffffff1f;
// split keystream into array
for (pos=0; pos<8; pos++) {
ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
}
// find possible states for this keystream
state = lfsr_common_prefix_ex(nr, ks3x);
if (!state) {
PrintAndLog("Failed getting states");
return 1;
}
state_s = (int64_t*)state;
uint32_t xored = uid ^ nt;
for (i = 0; (state) && ((state + i)->odd != -1); i++) {
lfsr_rollback_word(state + i, xored, 0);
crypto1_get_lfsr(state + i, &key_recovered);
*(state_s + i) = key_recovered;
}
qsort(state_s, i, sizeof(int64_t), compar_intA);
*(state_s + i) = -1;
// first call to this function. clear all other stuff and set new found states.
if (last_keylist == NULL) {
free(last_keylist);
last_keylist = state_s;
PrintAndLog("parity is all zero, testing special attack. First call, this attack needs at least two calls. Hold on...");
PrintAndLog("uid(%08x) nt(%08x) ks(%016" PRIx64") nr(%08x)", uid, nt, ks_info, nr);
return 1;
}
PrintAndLog("uid(%08x) nt(%08x) ks(%016" PRIx64") nr(%08x)", uid, nt, ks_info, nr);
//Create the intersection:
int64_t *p1, *p2, *p3;
p1 = p3 = last_keylist;
p2 = state_s;
while ( *p1 != -1 && *p2 != -1 ) {
if (compar_intA(p1, p2) == 0) {
PrintAndLog("p1:%" PRIx64" p2:%" PRIx64" p3:%" PRIx64" key:%012" PRIx64
, (uint64_t)(p1-last_keylist)
, (uint64_t)(p2-state_s)
, (uint64_t)(p3-last_keylist)
, *p1
);
*p3++ = *p1++;
p2++;
}
else {
while (compar_intA(p1, p2) == -1) ++p1;
while (compar_intA(p1, p2) == 1) ++p2;
}
}
key_count = p3 - last_keylist;
PrintAndLog("key_count: %d", key_count);
if ( key_count == 0 ){
free(state);
state = NULL;
return 0;
}
uint8_t retval = 1;
// Validate all key candidates with testing each of them with mfCheckKeys
uint8_t keyBlock[6] = {0,0,0,0,0,0};
uint64_t key64;
for (i = 0; i < key_count; i++) {
key64 = *(last_keylist + i);
num_to_bytes(key64, 6, keyBlock);
key64 = 0;
if (!mfCheckKeys(blockno, keytype, false, 1, keyBlock, &key64)) {
*key = key64;
retval = 0;
goto out;
}
}
out:
free(last_keylist);
last_keylist = NULL;
free(state);
state = NULL;
return retval;
}
// 32 bit recover key from 2 nonces, with same nonce
bool tryMfk32(nonces_t data, uint64_t *outputkey, bool verbose) {
struct Crypto1State *s,*t;
uint64_t outkey = 0;
uint64_t key=0; // recovered key
uint32_t uid = data.cuid;
uint32_t nt = data.nonce; // first tag challenge (nonce)
uint32_t nr0_enc = data.nr; // first encrypted reader challenge
uint32_t ar0_enc = data.ar; // first encrypted reader response
uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
uint32_t ar1_enc = data.ar2; // second encrypted reader response
bool isSuccess = false;
uint8_t counter = 0;
clock_t t1 = clock();
uint32_t p64 = prng_successor(nt, 64);
if ( verbose ) {
PrintAndLog("Recovering key for:");
PrintAndLog(" uid: %08x",uid);
PrintAndLog(" nt: %08x",nt);
PrintAndLog(" {nr_0}: %08x",nr0_enc);
PrintAndLog(" {ar_0}: %08x",ar0_enc);
PrintAndLog(" {nr_1}: %08x",nr1_enc);
PrintAndLog(" {ar_1}: %08x",ar1_enc);
PrintAndLog("\nLFSR succesors of the tag challenge:");
PrintAndLog(" nt': %08x", p64);
PrintAndLog(" nt'': %08x", prng_successor(p64, 32));
}
s = lfsr_recovery32(ar0_enc ^ p64, 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) ^ p64)) {
outkey = key;
++counter;
if (counter==20) break;
}
}
isSuccess = (counter > 0);
t1 = clock() - t1;
if ( t1 > 0 ) PrintAndLog("Time in mfkey32: %.0f ticks - possible keys %d", (float)t1, counter);
*outputkey = ( isSuccess ) ? outkey : 0;
crypto1_destroy(s);
return isSuccess;
}
bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey, bool verbose) {
struct Crypto1State *s, *t;
uint64_t outkey = 0;
uint64_t key = 0; // recovered key
uint32_t uid = data.cuid;
uint32_t nt0 = data.nonce; // first tag challenge (nonce)
uint32_t nr0_enc = data.nr; // first encrypted reader challenge
uint32_t ar0_enc = data.ar; // first encrypted reader response
//uint32_t uid1 = LE32TOH(data+16);
uint32_t nt1 = data.nonce2; // second tag challenge (nonce)
uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
uint32_t ar1_enc = data.ar2; // second encrypted reader response
bool isSuccess = false;
int counter = 0;
clock_t t1 = clock();
uint32_t p640 = prng_successor(nt0, 64);
uint32_t p641 = prng_successor(nt1, 64);
if (verbose) {
PrintAndLog("Recovering key for:");
PrintAndLog(" uid: %08x", uid);
PrintAndLog(" nt_0: %08x", nt0);
PrintAndLog(" {nr_0}: %08x", nr0_enc);
PrintAndLog(" {ar_0}: %08x", ar0_enc);
PrintAndLog(" nt_1: %08x", nt1);
PrintAndLog(" {nr_1}: %08x", nr1_enc);
PrintAndLog(" {ar_1}: %08x", ar1_enc);
PrintAndLog("\nLFSR succesors of the tag challenge:");
PrintAndLog(" nt': %08x", p640);
PrintAndLog(" nt'': %08x", prng_successor(p640, 32));
}
s = lfsr_recovery32(ar0_enc ^ p640, 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 ^ nt0, 0);
crypto1_get_lfsr(t, &key);
crypto1_word(t, uid ^ nt1, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ p641)) {
outkey=key;
++counter;
if (counter==20) break;
}
}
isSuccess = (counter > 0);
t1 = clock() - t1;
if (verbose) {
if ( t1 > 0 ) PrintAndLog("Time in mfkey32_moebius: %.0f ticks - possible keys %d", (float)t1, counter);
}
*outputkey = ( isSuccess ) ? outkey : 0;
crypto1_destroy(s);
return isSuccess;
}
// 64 bit recover key from a full authentication. (sniffed)
int tryMfk64_ex(uint8_t *data, uint64_t *outputkey){
uint32_t uid = LE32TOH(data);
uint32_t nt = LE32TOH(data+4); // tag challenge
uint32_t nr_enc = LE32TOH(data+8); // encrypted reader challenge
uint32_t ar_enc = LE32TOH(data+12); // encrypted reader response
uint32_t at_enc = LE32TOH(data+16); // encrypted tag response
return tryMfk64(uid, nt, nr_enc, ar_enc, at_enc, outputkey);
}
int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, 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");
clock_t t1 = clock();
// Extract the keystream from the messages
ks2 = ar_enc ^ prng_successor(nt, 64);
ks3 = at_enc ^ prng_successor(nt, 96);
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);
PrintAndLog("Found Key: [%012" PRIx64 "]", key);
t1 = clock() - t1;
if ( t1 > 0 ) PrintAndLog("Time in mfkey64: %.0f ticks", (float)t1);
*outputkey = key;
crypto1_destroy(revstate);
return 0;
}

View file

@ -1,34 +0,0 @@
//-----------------------------------------------------------------------------
// Merlok - June 2011
// Roel - Dec 2009
// Unknown author
// iceman - may 2015
// marshmellow42 - june 2016
// 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 <stdio.h>
#include <stdlib.h>
#include "crapto1.h"
#include "common.h"
#include "mifare.h" // nonces_t struct
#include "ui.h" // PrintAndLog
#include "proxmark3.h"
#include "mifarehost.h"
extern int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key);
extern int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint64_t * key);
//iceman, added these to be able to crack key direct from "hf 14 sim" && "hf mf sim"
bool tryMfk32(nonces_t data, uint64_t *outputkey, bool verbose );
bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey, bool verbose); // <<-- this one has best success
int tryMfk64_ex(uint8_t *data, uint64_t *outputkey );
int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey);
#endif

View file

@ -35,67 +35,8 @@ static void __attribute__((constructor)) fill_lut()
typedef struct bucket {
uint32_t *head;
uint32_t *bp;
} bucket_t;
typedef bucket_t bucket_array_t[2][0x100];
typedef struct bucket_info {
struct {
uint32_t *head, *tail;
} bucket_info[2][0x100];
uint32_t numbuckets;
} bucket_info_t;
static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
uint32_t* const ostart, uint32_t* const ostop,
bucket_info_t *bucket_info, bucket_array_t bucket)
{
uint32_t *p1, *p2;
uint32_t *start[2];
uint32_t *stop[2];
start[0] = estart;
stop[0] = estop;
start[1] = ostart;
stop[1] = ostop;
// init buckets to be empty
for (uint32_t i = 0; i < 2; i++) {
for (uint32_t j = 0x00; j <= 0xff; j++) {
bucket[i][j].bp = bucket[i][j].head;
}
}
// sort the lists into the buckets based on the MSB (contribution bits)
for (uint32_t i = 0; i < 2; i++) {
for (p1 = start[i]; p1 <= stop[i]; p1++) {
uint32_t bucket_index = (*p1 & 0xff000000) >> 24;
*(bucket[i][bucket_index].bp++) = *p1;
}
}
// write back intersecting buckets as sorted list.
// fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets.
uint32_t nonempty_bucket;
for (uint32_t i = 0; i < 2; i++) {
p1 = start[i];
nonempty_bucket = 0;
for (uint32_t j = 0x00; j <= 0xff; j++) {
if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only
bucket_info->bucket_info[i][nonempty_bucket].head = p1;
for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++);
bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1;
nonempty_bucket++;
}
}
bucket_info->numbuckets = nonempty_bucket;
}
}
/** binsearch
* Binary search for the first occurence of *stop's MSB in sorted [start,stop]
*/
@ -268,12 +209,11 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in)
recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket);
out:
free(odd_head);
free(even_head);
for (uint32_t i = 0; i < 2; i++)
for (uint32_t j = 0; j <= 0xff; j++)
free(bucket[i][j].head);
free(odd_head);
free(even_head);
return statelist;
}
@ -393,9 +333,21 @@ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb)
*/
uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb)
{
/*
int i, ret=0;
for (i = 7; i >= 0; --i)
ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i;
*/
// unfold loop 20160112
uint8_t ret = 0;
ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7;
ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6;
ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5;
ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4;
ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3;
ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2;
ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1;
ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0;
return ret;
}
/** lfsr_rollback_word
@ -403,10 +355,49 @@ uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb)
*/
uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb)
{
/*
int i;
uint32_t ret = 0;
for (i = 31; i >= 0; --i)
ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24);
*/
// unfold loop 20160112
uint32_t ret = 0;
ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24);
ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24);
return ret;
}
@ -458,18 +449,18 @@ static uint32_t fastfwd[2][8] = {
uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
{
uint32_t *candidates = malloc(4 << 10);
if(!candidates) return 0;
if (!candidates) return 0;
uint32_t c, entry;
int size = 0, i, good;
for(i = 0; i < 1 << 21; ++i) {
for(c = 0, good = 1; good && c < 8; ++c) {
for (i = 0; i < 1 << 21; ++i) {
for (c = 0, good = 1; good && c < 8; ++c) {
entry = i ^ fastfwd[isodd][c];
good &= (BIT(ks[c], isodd) == filter(entry >> 1));
good &= (BIT(ks[c], isodd + 2) == filter(entry));
}
if(good)
if (good)
candidates[size++] = i;
}
@ -481,9 +472,7 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
/** check_pfx_parity
* helper function which eliminates possible secret states using parity bits
*/
static struct Crypto1State*
check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
uint32_t odd, uint32_t even, struct Crypto1State* sl, uint32_t no_par)
static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl, uint32_t no_par)
{
uint32_t ks1, nr, ks2, rr, ks3, c, good = 1;
@ -524,8 +513,8 @@ check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
* It returns a zero terminated list of possible cipher states after the
* tag nonce was fed in
*/
struct Crypto1State*
lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint32_t no_par)
struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint32_t no_par)
{
struct Crypto1State *statelist, *s;
uint32_t *odd, *even, *o, *e, top;

View file

@ -21,6 +21,8 @@
#define CRAPTO1_INCLUDED
#include <stdint.h>
#include <stdbool.h>
#include "bucketsort.h"
#ifdef __cplusplus
extern "C" {
#endif

View file

@ -72,7 +72,7 @@ void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr)
}
uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted)
{
uint32_t feedin, tmp;
uint32_t feedin, t;
uint8_t ret = filter(s->odd);
feedin = ret & !!is_encrypted;
@ -81,28 +81,77 @@ uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted)
feedin ^= LF_POLY_EVEN & s->even;
s->even = s->even << 1 | evenparity32(feedin);
tmp = s->odd;
t = s->odd;
s->odd = s->even;
s->even = tmp;
s->even = t;
return ret;
}
uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted)
{
/*
uint8_t i, ret = 0;
for (i = 0; i < 8; ++i)
ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i;
*/
// unfold loop 20161012
uint8_t ret = 0;
ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0;
ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1;
ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2;
ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3;
ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4;
ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5;
ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6;
ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7;
return ret;
}
uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted)
{
/*
uint32_t i, ret = 0;
for (i = 0; i < 32; ++i)
ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24);
*/
//unfold loop 2016012
uint32_t ret = 0;
ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24);
ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24);
return ret;
}