mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
chg: mfkeys: adapting old refactoring (@piwi)
This commit is contained in:
@@ -1,21 +1,20 @@
|
|||||||
|
VPATH = ../../common ../../common/crapto1 ../../client
|
||||||
CC = gcc
|
CC = gcc
|
||||||
LD = gcc
|
LD = gcc
|
||||||
CFLAGS += -std=c99 -march=native -Wall -Winline -O3
|
CFLAGS += -std=c99 -D_ISOC99_SOURCE -I../../include -I../../common -I../../client -Wall -O3
|
||||||
LDFLAGS +=
|
LDFLAGS +=
|
||||||
|
|
||||||
OBJS = crapto1.o crypto1.o
|
OBJS = crypto1.o crapto1.o parity.o util_posix.o bucketsort.o
|
||||||
HEADERS = crapto1.h
|
EXES = mfkey32 mfkey32v2 mfkey64
|
||||||
EXES = mfkey64 mfkey32 mfkey32v2
|
WINEXES = $(patsubst %, %.exe, $(EXES))
|
||||||
WINEXE = $(patsubst %, %.exe, $(EXES))
|
|
||||||
|
|
||||||
all: $(OBJS) $(EXES)
|
all: $(OBJS) $(EXES)
|
||||||
|
|
||||||
%.o : %.c
|
%.o : %.c
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
% : %.c
|
% : %.c $(OBJS)
|
||||||
$(LD) $(CFLAGS) -o $@ $(OBJS) $<
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJS) $(EXES) $(WINEXE)
|
rm -f $(OBJS) $(EXES) $(WINEXES)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,93 +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>
|
|
||||||
#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]);
|
|
||||||
|
|
||||||
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);
|
|
||||||
#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
|
|
||||||
@@ -1,139 +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);
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
#define __STDC_FORMAT_MACROS
|
#define __STDC_FORMAT_MACROS
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "crapto1.h"
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "crapto1/crapto1.h"
|
||||||
|
#include "util_posix.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
struct Crypto1State *s, *t;
|
struct Crypto1State *s, *t;
|
||||||
@@ -15,7 +17,7 @@ int main(int argc, char *argv[]) {
|
|||||||
uint32_t ar1_enc; // second encrypted reader response
|
uint32_t ar1_enc; // second encrypted reader response
|
||||||
uint32_t ks2; // keystream used to encrypt reader response
|
uint32_t ks2; // keystream used to encrypt reader response
|
||||||
|
|
||||||
printf("MIFARE Classic key recovery - based 32 bits of keystream\n");
|
printf("MIFARE Classic key recovery - based on 32 bits of keystream\n");
|
||||||
printf("Recover key from two 32-bit reader authentication answers only!\n\n");
|
printf("Recover key from two 32-bit reader authentication answers only!\n\n");
|
||||||
|
|
||||||
if (argc < 7) {
|
if (argc < 7) {
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#define __STDC_FORMAT_MACROS
|
#define __STDC_FORMAT_MACROS
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "crapto1.h"
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "crapto1/crapto1.h"
|
||||||
|
#include "util_posix.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
struct Crypto1State *s, *t;
|
struct Crypto1State *s, *t;
|
||||||
|
|||||||
+10
-8
@@ -1,9 +1,10 @@
|
|||||||
#define __STDC_FORMAT_MACROS
|
#define __STDC_FORMAT_MACROS
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "crapto1.h"
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "crapto1/crapto1.h"
|
||||||
|
#include "util_posix.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
struct Crypto1State *revstate;
|
struct Crypto1State *revstate;
|
||||||
@@ -58,13 +59,14 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// Generate lfsr succesors of the tag challenge
|
// Generate lfsr succesors of the tag challenge
|
||||||
printf("\nLFSR succesors of the tag challenge:\n");
|
printf("\nLFSR succesors of the tag challenge:\n");
|
||||||
printf(" nt': %08x\n", prng_successor(nt, 64));
|
uint32_t p64 = prng_successor(nt, 64);
|
||||||
printf(" nt'': %08x\n", prng_successor(nt, 96));
|
printf(" nt': %08x\n", p64);
|
||||||
|
printf(" nt'': %08x\n", prng_successor(p64, 32));
|
||||||
|
|
||||||
// Extract the keystream from the messages
|
// Extract the keystream from the messages
|
||||||
printf("\nKeystream used to generate {ar} and {at}:\n");
|
printf("\nKeystream used to generate {ar} and {at}:\n");
|
||||||
ks2 = ar_enc ^ prng_successor(nt, 64);
|
ks2 = ar_enc ^ p64;
|
||||||
ks3 = at_enc ^ prng_successor(nt, 96);
|
ks3 = at_enc ^ prng_successor(p64, 32);
|
||||||
printf(" ks2: %08x\n", ks2);
|
printf(" ks2: %08x\n", ks2);
|
||||||
printf(" ks3: %08x\n", ks3);
|
printf(" ks3: %08x\n", ks3);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user