make style

This commit is contained in:
Philippe Teuwen
2019-03-10 00:00:59 +01:00
parent 0d9223a547
commit 0373696662
483 changed files with 56514 additions and 52451 deletions

View File

@@ -114,8 +114,8 @@ uint8_t _select(bool x, bool y, uint8_t r)
bool r7 = r & 0x1;
bool z0 = (r0 & r2) ^ (r1 & !r3) ^ (r2 | r4);
bool z1 = (r0 | r2) ^ ( r5 | r7) ^ r1 ^ r6 ^ x ^ y;
bool z2 = (r3 & !r5) ^ (r4 & r6 ) ^ r7 ^ x;
bool z1 = (r0 | r2) ^ (r5 | r7) ^ r1 ^ r6 ^ x ^ y;
bool z2 = (r3 & !r5) ^ (r4 & r6) ^ r7 ^ x;
// The three bitz z0.. z1 are packed into a uint8_t:
// 00000ZZZ
@@ -139,13 +139,13 @@ uint8_t _select(bool x, bool y, uint8_t r)
* @param s - state
* @param k - array containing 8 bytes
**/
State successor(uint8_t* k, State s, bool y)
State successor(uint8_t *k, State s, bool y)
{
bool r0 = s.r >> 7 & 0x1;
bool r4 = s.r >> 3 & 0x1;
bool r7 = s.r & 0x1;
State successor = {0,0,0,0};
State successor = {0, 0, 0, 0};
successor.t = s.t >> 1;
successor.t |= (T(s) ^ r0 ^ r4) << 15;
@@ -155,8 +155,8 @@ State successor(uint8_t* k, State s, bool y)
bool Tt = T(s);
successor.l = ((k[_select(Tt,y,s.r)] ^ successor.b) + s.l+s.r ) & 0xFF;
successor.r = ((k[_select(Tt,y,s.r)] ^ successor.b) + s.l ) & 0xFF;
successor.l = ((k[_select(Tt, y, s.r)] ^ successor.b) + s.l + s.r) & 0xFF;
successor.r = ((k[_select(Tt, y, s.r)] ^ successor.b) + s.l) & 0xFF;
return successor;
}
@@ -166,14 +166,13 @@ State successor(uint8_t* k, State s, bool y)
* to multiple bit input x ∈ F n 2 which we define as
* @param k - array containing 8 bytes
**/
State suc(uint8_t* k,State s, BitstreamIn *bitstream)
State suc(uint8_t *k, State s, BitstreamIn *bitstream)
{
if(bitsLeft(bitstream) == 0)
{
if (bitsLeft(bitstream) == 0) {
return s;
}
bool lastbit = tailBit(bitstream);
return successor(k,suc(k,s,bitstream), lastbit);
return successor(k, suc(k, s, bitstream), lastbit);
}
/**
@@ -184,17 +183,16 @@ State suc(uint8_t* k,State s, BitstreamIn *bitstream)
* output(k, s, x 0 . . . x n ) = output(s) · output(k, s , x 1 . . . x n )
* where s = suc(k, s, x 0 ).
**/
void output(uint8_t* k,State s, BitstreamIn* in, BitstreamOut* out)
void output(uint8_t *k, State s, BitstreamIn *in, BitstreamOut *out)
{
if(bitsLeft(in) == 0)
{
if (bitsLeft(in) == 0) {
return;
}
pushBit(out,(s.r >> 2) & 1);
pushBit(out, (s.r >> 2) & 1);
//Remove first bit
uint8_t x0 = headBit(in);
State ss = successor(k,s,x0);
output(k,ss,in, out);
State ss = successor(k, s, x0);
output(k, ss, in, out);
}
/**
@@ -202,22 +200,22 @@ void output(uint8_t* k,State s, BitstreamIn* in, BitstreamOut* out)
* key k ∈ (F 82 ) 8 and outputs the initial cipher state s =< l, r, t, b >
**/
State init(uint8_t* k)
State init(uint8_t *k)
{
State s = {
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b
0xE012 // t
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b
0xE012 // t
};
return s;
}
void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out)
void MAC(uint8_t *k, BitstreamIn input, BitstreamOut out)
{
uint8_t zeroes_32[] = {0,0,0,0};
BitstreamIn input_32_zeroes = {zeroes_32,sizeof(zeroes_32)*8,0};
State initState = suc(k,init(k),&input);
output(k,initState,&input_32_zeroes,&out);
uint8_t zeroes_32[] = {0, 0, 0, 0};
BitstreamIn input_32_zeroes = {zeroes_32, sizeof(zeroes_32) * 8, 0};
State initState = suc(k, init(k), &input);
output(k, initState, &input_32_zeroes, &out);
}
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
@@ -231,9 +229,9 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
reverse_arraybytes(cc_nr, 12);
BitstreamIn bitstream = {cc_nr, 12 * 8, 0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key,bitstream, out);
uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamOut out = { dest, sizeof(dest) * 8, 0 };
MAC(div_key, bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
memcpy(mac, dest, 4);
@@ -244,15 +242,15 @@ void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_ke
{
uint8_t *address_data;
uint8_t div_key[8];
address_data = (uint8_t*) calloc(address_data_size, sizeof(uint8_t));
address_data = (uint8_t *) calloc(address_data_size, sizeof(uint8_t));
memcpy(address_data, address_data_p, address_data_size);
memcpy(div_key, div_key_p, 8);
reverse_arraybytes(address_data, address_data_size);
BitstreamIn bitstream = {address_data, address_data_size * 8, 0};
uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 };
uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamOut out = { dest, sizeof(dest) * 8, 0 };
MAC(div_key, bitstream, out);
//The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest));
@@ -267,15 +265,15 @@ int testMAC()
PrintAndLogDevice(SUCCESS, "Testing MAC calculation...");
//From the "dismantling.IClass" paper:
uint8_t cc_nr[] = {0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0};
uint8_t cc_nr[] = {0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0};
//From the paper
uint8_t div_key[8] = {0xE0,0x33,0xCA,0x41,0x9A,0xEE,0x43,0xF9};
uint8_t correct_MAC[4] = {0x1d,0x49,0xC9,0xDA};
uint8_t div_key[8] = {0xE0, 0x33, 0xCA, 0x41, 0x9A, 0xEE, 0x43, 0xF9};
uint8_t correct_MAC[4] = {0x1d, 0x49, 0xC9, 0xDA};
uint8_t calculated_mac[4] = {0};
doMAC(cc_nr,div_key, calculated_mac);
doMAC(cc_nr, div_key, calculated_mac);
if (memcmp(calculated_mac, correct_MAC,4) == 0) {
if (memcmp(calculated_mac, correct_MAC, 4) == 0) {
PrintAndLogDevice(SUCCESS, "MAC calculation OK!");
} else {
PrintAndLogDevice(FAILED, "FAILED: MAC calculation failed:");

View File

@@ -41,7 +41,7 @@
#include <stdint.h>
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
void doMAC_N(uint8_t *address_data_p,uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]);
void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]);
#ifndef ON_DEVICE
int testMAC();

View File

@@ -46,35 +46,35 @@
* @param stream
* @return
*/
bool headBit( BitstreamIn *stream)
bool headBit(BitstreamIn *stream)
{
int bytepos = stream->position >> 3; // divide by 8
int bitpos = (stream->position++) & 7; // mask out 00000111
return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1;
return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1;
}
/**
* @brief Return and remove the last bit (xn) in the stream: <x0 x1 x2 ... xn>
* @param stream
* @return
*/
bool tailBit( BitstreamIn *stream)
bool tailBit(BitstreamIn *stream)
{
int bitpos = stream->numbits -1 - (stream->position++);
int bitpos = stream->numbits - 1 - (stream->position++);
int bytepos= bitpos >> 3;
int bytepos = bitpos >> 3;
bitpos &= 7;
return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1;
return (*(stream->buffer + bytepos) >> (7 - bitpos)) & 1;
}
/**
* @brief Pushes bit onto the stream
* @param stream
* @param bit
*/
void pushBit( BitstreamOut* stream, bool bit)
void pushBit(BitstreamOut *stream, bool bit)
{
int bytepos = stream->position >> 3; // divide by 8
int bitpos = stream->position & 7;
*(stream->buffer+bytepos) |= (bit & 1) << (7 - bitpos);
*(stream->buffer + bytepos) |= (bit & 1) << (7 - bitpos);
stream->position++;
stream->numbits++;
}
@@ -85,7 +85,7 @@ void pushBit( BitstreamOut* stream, bool bit)
* @param stream
* @param bits
*/
void push6bits( BitstreamOut* stream, uint8_t bits)
void push6bits(BitstreamOut *stream, uint8_t bits)
{
pushBit(stream, bits & 0x20);
pushBit(stream, bits & 0x10);
@@ -100,7 +100,7 @@ void push6bits( BitstreamOut* stream, uint8_t bits)
* @param stream
* @return number of bits left in stream
*/
int bitsLeft( BitstreamIn *stream)
int bitsLeft(BitstreamIn *stream)
{
return stream->numbits - stream->position;
}
@@ -114,7 +114,7 @@ int numBits(BitstreamOut *stream)
return stream->numbits;
}
void x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
void x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest)
{
while (len--) {
dest[len] = (uint8_t) n;
@@ -122,74 +122,75 @@ void x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
}
}
uint64_t x_bytes_to_num(uint8_t* src, size_t len)
uint64_t x_bytes_to_num(uint8_t *src, size_t len)
{
uint64_t num = 0;
while (len--)
{
while (len--) {
num = (num << 8) | (*src);
src++;
}
return num;
}
uint8_t reversebytes(uint8_t b) {
uint8_t reversebytes(uint8_t b)
{
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
return b;
}
void reverse_arraybytes(uint8_t* arr, size_t len)
void reverse_arraybytes(uint8_t *arr, size_t len)
{
uint8_t i;
for( i =0; i< len ; i++)
{
for (i = 0; i < len ; i++) {
arr[i] = reversebytes(arr[i]);
}
}
void reverse_arraycopy(uint8_t* arr, uint8_t* dest, size_t len)
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len)
{
uint8_t i;
for( i =0; i< len ; i++)
{
for (i = 0; i < len ; i++) {
dest[i] = reversebytes(arr[i]);
}
}
void printarr(char * name, uint8_t* arr, int len) {
void printarr(char *name, uint8_t *arr, int len)
{
int cx, i;
size_t outsize = 40 + strlen(name) + len*5;
char* output = calloc(outsize, sizeof(char));
cx = snprintf(output,outsize, "uint8_t %s[] = {", name);
for (i=0; i < len; i++) {
cx += snprintf(output+cx,outsize-cx,"0x%02x,",*(arr+i));//5 bytes per byte
size_t outsize = 40 + strlen(name) + len * 5;
char *output = calloc(outsize, sizeof(char));
cx = snprintf(output, outsize, "uint8_t %s[] = {", name);
for (i = 0; i < len; i++) {
cx += snprintf(output + cx, outsize - cx, "0x%02x,", *(arr + i)); //5 bytes per byte
}
cx += snprintf(output+cx,outsize-cx,"};");
cx += snprintf(output + cx, outsize - cx, "};");
PrintAndLogDevice(NORMAL, output);
free(output);
}
void printvar(char * name, uint8_t* arr, int len) {
void printvar(char *name, uint8_t *arr, int len)
{
int cx, i;
size_t outsize = 40 + strlen(name) + len*2;
char* output = calloc(outsize, sizeof(char));
cx = snprintf(output,outsize,"%s = ", name);
for (i=0; i < len; i++) {
cx += snprintf(output+cx,outsize-cx,"%02x",*(arr+i));//2 bytes per byte
size_t outsize = 40 + strlen(name) + len * 2;
char *output = calloc(outsize, sizeof(char));
cx = snprintf(output, outsize, "%s = ", name);
for (i = 0; i < len; i++) {
cx += snprintf(output + cx, outsize - cx, "%02x", *(arr + i)); //2 bytes per byte
}
PrintAndLogDevice(NORMAL, output);
free(output);
}
void printarr_human_readable(char * title, uint8_t* arr, int len) {
void printarr_human_readable(char *title, uint8_t *arr, int len)
{
int cx, i;
size_t outsize = 100 + strlen(title) + len*4;
char* output = calloc(outsize, sizeof(char));
cx = snprintf(output,outsize, "\n\t%s\n", title);
for (i=0; i < len; i++) {
size_t outsize = 100 + strlen(title) + len * 4;
char *output = calloc(outsize, sizeof(char));
cx = snprintf(output, outsize, "\n\t%s\n", title);
for (i = 0; i < len; i++) {
if (i % 16 == 0)
cx += snprintf(output+cx,outsize-cx,"\n%02x| ", i );
cx += snprintf(output+cx,outsize-cx, "%02x ",*(arr+i));
cx += snprintf(output + cx, outsize - cx, "\n%02x| ", i);
cx += snprintf(output + cx, outsize - cx, "%02x ", *(arr + i));
}
PrintAndLogDevice(NORMAL, output);
free(output);
@@ -202,24 +203,23 @@ void printarr_human_readable(char * title, uint8_t* arr, int len) {
#ifndef ON_DEVICE
int testBitStream()
{
uint8_t input [] = {0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF};
uint8_t output [] = {0,0,0,0,0,0,0,0};
BitstreamIn in = { input, sizeof(input) * 8,0};
BitstreamOut out = { output, 0,0}
;
uint8_t input [] = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF};
uint8_t output [] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamIn in = { input, sizeof(input) * 8, 0};
BitstreamOut out = { output, 0, 0}
;
while (bitsLeft(&in) > 0) {
pushBit(&out, headBit(&in));
//printf("Bits left: %d\n", bitsLeft(&in));
//printf("Bits out: %d\n", numBits(&out));
}
if(memcmp(input, output, sizeof(input)) == 0) {
if (memcmp(input, output, sizeof(input)) == 0) {
PrintAndLogDevice(SUCCESS, " Bitstream test 1 ok");
} else {
PrintAndLogDevice(FAILED, " Bitstream test 1 failed");
uint8_t i;
for(i = 0 ; i < sizeof(input) ; i++)
{
for (i = 0 ; i < sizeof(input) ; i++) {
PrintAndLogDevice(NORMAL, " IN %02x, OUT %02x", input[i], output[i]);
}
return 1;
@@ -229,13 +229,13 @@ int testBitStream()
int testReversedBitstream()
{
uint8_t input [] = {0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF};
uint8_t reverse [] = {0,0,0,0,0,0,0,0};
uint8_t output [] = {0,0,0,0,0,0,0,0};
BitstreamIn in = { input, sizeof(input) * 8,0};
BitstreamOut out = { output, 0,0};
BitstreamIn reversed_in = { reverse, sizeof(input)*8,0};
BitstreamOut reversed_out = { reverse,0 ,0};
uint8_t input [] = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF};
uint8_t reverse [] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t output [] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamIn in = { input, sizeof(input) * 8, 0};
BitstreamOut out = { output, 0, 0};
BitstreamIn reversed_in = { reverse, sizeof(input) * 8, 0};
BitstreamOut reversed_out = { reverse, 0, 0};
while (bitsLeft(&in) > 0) {
pushBit(&reversed_out, tailBit(&in));
@@ -251,7 +251,7 @@ int testReversedBitstream()
PrintAndLogDevice(FAILED, " Bitstream test 2 failed");
uint8_t i;
for (i = 0 ; i < sizeof(input) ; i++) {
PrintAndLogDevice(NORMAL, " IN %02x, MIDDLE: %02x, OUT %02x", input[i],reverse[i], output[i]);
PrintAndLogDevice(NORMAL, " IN %02x, MIDDLE: %02x, OUT %02x", input[i], reverse[i], output[i]);
}
return 1;
}

View File

@@ -43,33 +43,33 @@
#include <stdlib.h>
typedef struct {
uint8_t * buffer;
uint8_t *buffer;
uint8_t numbits;
uint8_t position;
} BitstreamIn;
typedef struct {
uint8_t * buffer;
uint8_t *buffer;
uint8_t numbits;
uint8_t position;
} BitstreamOut;
bool headBit( BitstreamIn *stream);
bool tailBit( BitstreamIn *stream);
void pushBit( BitstreamOut *stream, bool bit);
int bitsLeft( BitstreamIn *stream);
bool headBit(BitstreamIn *stream);
bool tailBit(BitstreamIn *stream);
void pushBit(BitstreamOut *stream, bool bit);
int bitsLeft(BitstreamIn *stream);
#ifndef ON_DEVICE
int testCipherUtils(void);
int testMAC();
#endif
void push6bits( BitstreamOut* stream, uint8_t bits);
void push6bits(BitstreamOut *stream, uint8_t bits);
void EncryptDES(bool key[56], bool outBlk[64], bool inBlk[64], int verbose) ;
void x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t x_bytes_to_num(uint8_t* src, size_t len);
void x_num_to_bytes(uint64_t n, size_t len, uint8_t *dest);
uint64_t x_bytes_to_num(uint8_t *src, size_t len);
uint8_t reversebytes(uint8_t b);
void reverse_arraybytes(uint8_t* arr, size_t len);
void reverse_arraycopy(uint8_t* arr, uint8_t* dest, size_t len);
void printarr(char * name, uint8_t* arr, int len);
void printvar(char * name, uint8_t* arr, int len);
void printarr_human_readable(char * title, uint8_t* arr, int len);
void reverse_arraybytes(uint8_t *arr, size_t len);
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len);
void printarr(char *name, uint8_t *arr, int len);
void printvar(char *name, uint8_t *arr, int len);
void printarr_human_readable(char *title, uint8_t *arr, int len);
#endif // CIPHERUTILS_H

View File

@@ -69,17 +69,18 @@
* @param key
* @param dest
*/
void permutekey(uint8_t key[8], uint8_t dest[8]) {
void permutekey(uint8_t key[8], uint8_t dest[8])
{
int i;
for(i = 0 ; i < 8 ; i++) {
dest[i] = (((key[7] & (0x80 >> i)) >> (7-i)) << 7) |
(((key[6] & (0x80 >> i)) >> (7-i)) << 6) |
(((key[5] & (0x80 >> i)) >> (7-i)) << 5) |
(((key[4] & (0x80 >> i)) >> (7-i)) << 4) |
(((key[3] & (0x80 >> i)) >> (7-i)) << 3) |
(((key[2] & (0x80 >> i)) >> (7-i)) << 2) |
(((key[1] & (0x80 >> i)) >> (7-i)) << 1) |
(((key[0] & (0x80 >> i)) >> (7-i)) << 0);
for (i = 0 ; i < 8 ; i++) {
dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) |
(((key[6] & (0x80 >> i)) >> (7 - i)) << 6) |
(((key[5] & (0x80 >> i)) >> (7 - i)) << 5) |
(((key[4] & (0x80 >> i)) >> (7 - i)) << 4) |
(((key[3] & (0x80 >> i)) >> (7 - i)) << 3) |
(((key[2] & (0x80 >> i)) >> (7 - i)) << 2) |
(((key[1] & (0x80 >> i)) >> (7 - i)) << 1) |
(((key[0] & (0x80 >> i)) >> (7 - i)) << 0);
}
}
/**
@@ -88,17 +89,18 @@ void permutekey(uint8_t key[8], uint8_t dest[8]) {
* @param key
* @param dest
*/
void permutekey_rev(uint8_t key[8], uint8_t dest[8]) {
void permutekey_rev(uint8_t key[8], uint8_t dest[8])
{
int i;
for(i = 0 ; i < 8 ; i++) {
dest[7-i] = (((key[0] & (0x80 >> i)) >> (7-i)) << 7) |
(((key[1] & (0x80 >> i)) >> (7-i)) << 6) |
(((key[2] & (0x80 >> i)) >> (7-i)) << 5) |
(((key[3] & (0x80 >> i)) >> (7-i)) << 4) |
(((key[4] & (0x80 >> i)) >> (7-i)) << 3) |
(((key[5] & (0x80 >> i)) >> (7-i)) << 2) |
(((key[6] & (0x80 >> i)) >> (7-i)) << 1) |
(((key[7] & (0x80 >> i)) >> (7-i)) << 0);
for (i = 0 ; i < 8 ; i++) {
dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) |
(((key[1] & (0x80 >> i)) >> (7 - i)) << 6) |
(((key[2] & (0x80 >> i)) >> (7 - i)) << 5) |
(((key[3] & (0x80 >> i)) >> (7 - i)) << 4) |
(((key[4] & (0x80 >> i)) >> (7 - i)) << 3) |
(((key[5] & (0x80 >> i)) >> (7 - i)) << 2) |
(((key[6] & (0x80 >> i)) >> (7 - i)) << 1) |
(((key[7] & (0x80 >> i)) >> (7 - i)) << 0);
}
}
@@ -108,8 +110,9 @@ void permutekey_rev(uint8_t key[8], uint8_t dest[8]) {
* @param val
* @return
*/
inline uint8_t rr(uint8_t val) {
return val >> 1 | (( val & 1) << 7);
inline uint8_t rr(uint8_t val)
{
return val >> 1 | ((val & 1) << 7);
}
/**
@@ -118,8 +121,9 @@ inline uint8_t rr(uint8_t val) {
* @param val
* @return
*/
inline uint8_t rl(uint8_t val) {
return val << 1 | (( val & 0x80) >> 7);
inline uint8_t rl(uint8_t val)
{
return val << 1 | ((val & 0x80) >> 7);
}
/**
@@ -128,8 +132,9 @@ inline uint8_t rl(uint8_t val) {
* @param val
* @return
*/
inline uint8_t swap(uint8_t val) {
return ((val >> 4) & 0xFF) | ((val &0xFF) << 4);
inline uint8_t swap(uint8_t val)
{
return ((val >> 4) & 0xFF) | ((val & 0xFF) << 4);
}
/**
@@ -138,15 +143,16 @@ inline uint8_t swap(uint8_t val) {
* @param csn the CSN used
* @param k output
*/
void hash1(uint8_t csn[] , uint8_t k[]) {
void hash1(uint8_t csn[], uint8_t k[])
{
k[0] = csn[0] ^ csn[1] ^ csn[2] ^ csn[3] ^ csn[4] ^ csn[5] ^ csn[6] ^ csn[7];
k[1] = csn[0] + csn[1] + csn[2] + csn[3] + csn[4] + csn[5] + csn[6] + csn[7];
k[2] = rr(swap( csn[2] + k[1] ));
k[3] = rl(swap( csn[3] + k[0] ));
k[4] = ~rr( csn[4] + k[2] ) + 1;
k[5] = ~rl( csn[5] + k[3] ) + 1;
k[6] = rr( csn[6] + (k[4] ^ 0x3c) );
k[7] = rl( csn[7] + (k[5] ^ 0xc3) );
k[2] = rr(swap(csn[2] + k[1]));
k[3] = rl(swap(csn[3] + k[0]));
k[4] = ~rr(csn[4] + k[2]) + 1;
k[5] = ~rl(csn[5] + k[3]) + 1;
k[6] = rr(csn[6] + (k[4] ^ 0x3c));
k[7] = rl(csn[7] + (k[5] ^ 0xc3));
k[7] &= 0x7F;
k[6] &= 0x7F;
@@ -162,11 +168,12 @@ Definition 14. Define the rotate key function rk : (F 82 ) 8 × N → (F 82 ) 8
rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
**/
void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) {
void rk(uint8_t *key, uint8_t n, uint8_t *outp_key)
{
memcpy(outp_key, key, 8);
uint8_t j;
while (n-- > 0) {
for (j=0; j < 8 ; j++)
for (j = 0; j < 8 ; j++)
outp_key[j] = rl(outp_key[j]);
}
return;
@@ -175,18 +182,20 @@ void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) {
static mbedtls_des_context ctx_enc;
static mbedtls_des_context ctx_dec;
void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output)
{
uint8_t key_std_format[8] = {0};
permutekey_rev(iclass_key, key_std_format);
mbedtls_des_setkey_dec( &ctx_dec, key_std_format);
mbedtls_des_crypt_ecb(&ctx_dec,input,output);
mbedtls_des_setkey_dec(&ctx_dec, key_std_format);
mbedtls_des_crypt_ecb(&ctx_dec, input, output);
}
void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output)
{
uint8_t key_std_format[8] = {0};
permutekey_rev(iclass_key, key_std_format);
mbedtls_des_setkey_enc( &ctx_enc, key_std_format);
mbedtls_des_crypt_ecb(&ctx_enc,input,output);
mbedtls_des_setkey_enc(&ctx_enc, key_std_format);
mbedtls_des_crypt_ecb(&ctx_enc, input, output);
}
/**
@@ -195,28 +204,29 @@ void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
* @param hash1 hash1
* @param key_sel output key_sel=h[hash1[i]]
*/
void hash2(uint8_t *key64, uint8_t *outp_keytable) {
void hash2(uint8_t *key64, uint8_t *outp_keytable)
{
/**
*Expected:
* High Security Key Table
00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/
**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/
uint8_t key64_negated[8] = {0};
uint8_t z[8][8]={{0},{0}};
uint8_t temp_output[8]={0};
uint8_t z[8][8] = {{0}, {0}};
uint8_t temp_output[8] = {0};
//calculate complement of key
int i;
for (i=0; i<8; i++)
key64_negated[i]= ~key64[i];
for (i = 0; i < 8; i++)
key64_negated[i] = ~key64[i];
// Once again, key is on iclass-format
desencrypt_iclass(key64, key64_negated, z[0]);
@@ -224,29 +234,29 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) {
// PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(NORMAL, "High security custom key (Kcus):");
// printvar("z0 ", z[0],8);
uint8_t y[8][8]={{0},{0}};
uint8_t y[8][8] = {{0}, {0}};
// y[0]=DES_dec(z[0],~key)
// Once again, key is on iclass-format
desdecrypt_iclass(z[0], key64_negated, y[0]);
// printvar("y0 ", y[0],8);
for (i=1; i<8; i++) {
for (i = 1; i < 8; i++) {
// z [i] = DES dec (rk(K cus , i), z [i1] )
rk(key64, i, temp_output);
//y [i] = DES enc (rk(K cus , i), y [i1] )
desdecrypt_iclass(temp_output,z[i-1], z[i]);
desencrypt_iclass(temp_output,y[i-1], y[i]);
desdecrypt_iclass(temp_output, z[i - 1], z[i]);
desencrypt_iclass(temp_output, y[i - 1], y[i]);
}
if (outp_keytable != NULL) {
for (i = 0 ; i < 8 ; i++) {
memcpy(outp_keytable+i*16,y[i],8);
memcpy(outp_keytable+8+i*16,z[i],8);
memcpy(outp_keytable + i * 16, y[i], 8);
memcpy(outp_keytable + 8 + i * 16, z[i], 8);
}
} else {
printarr_human_readable("hash2", outp_keytable,128);
printarr_human_readable("hash2", outp_keytable, 128);
}
}
@@ -266,9 +276,10 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) {
* @param i the number to read. Should be less than 127, or something is wrong...
* @return
*/
int _readFromDump(uint8_t dump[], dumpdata* item, uint8_t i) {
int _readFromDump(uint8_t dump[], dumpdata *item, uint8_t i)
{
size_t itemsize = sizeof(dumpdata);
memcpy(item, dump+i*itemsize, itemsize);
memcpy(item, dump + i * itemsize, itemsize);
if (true) {
printvar("csn", item->csn, sizeof(item->csn));
@@ -290,7 +301,8 @@ int _readFromDump(uint8_t dump[], dumpdata* item, uint8_t i) {
* @param keytable where to write found values.
* @return
*/
int bruteforceItem(dumpdata item, uint16_t keytable[]) {
int bruteforceItem(dumpdata item, uint16_t keytable[])
{
int errors = 0;
int found = false;
uint8_t key_sel_p[8] = {0};
@@ -317,7 +329,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
uint8_t bytes_to_recover[3] = {0};
uint8_t numbytes_to_recover = 0 ;
int i;
for (i=0; i<8; i++) {
for (i = 0; i < 8; i++) {
if (keytable[key_index[i]] & (CRACKED | BEING_CRACKED)) continue;
bytes_to_recover[numbytes_to_recover++] = key_index[i];
@@ -349,17 +361,17 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
bytes_to_recover = 3 --> endmask = 0x001000000
*/
uint32_t endmask = 1 << 8*numbytes_to_recover;
uint32_t endmask = 1 << 8 * numbytes_to_recover;
PrintAndLogDevice(NORMAL, "----------------------------");
for (i =0 ; i < numbytes_to_recover && numbytes_to_recover > 1; i++)
for (i = 0 ; i < numbytes_to_recover && numbytes_to_recover > 1; i++)
PrintAndLogDevice(INFO, "Bruteforcing byte %d", bytes_to_recover[i]);
while (!found && !(brute & endmask)) {
//Update the keytable with the brute-values
for (i=0; i < numbytes_to_recover; i++) {
for (i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] &= 0xFF00;
keytable[bytes_to_recover[i]] |= (brute >> (i*8) & 0xFF);
keytable[bytes_to_recover[i]] |= (brute >> (i * 8) & 0xFF);
}
// Piece together the key
@@ -382,7 +394,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
// success
if (memcmp(calculated_MAC, item.mac, 4) == 0) {
printf("\r\n");
for (i =0 ; i < numbytes_to_recover; i++) {
for (i = 0 ; i < numbytes_to_recover; i++) {
PrintAndLogDevice(INFO, "%d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]);
}
found = true;
@@ -391,26 +403,27 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
brute++;
if ((brute & 0xFFFF) == 0) {
printf("%3d,",(brute >> 16) & 0xFF);
if ( ((brute >> 16) % 0x10) == 0)
printf("%3d,", (brute >> 16) & 0xFF);
if (((brute >> 16) % 0x10) == 0)
printf("\n");
fflush(stdout);
}
}
if (!found) {
PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover);
PrintAndLogDevice(NORMAL, "\n");
PrintAndLogDevice(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover);
printvar("[!] CSN", item.csn, 8);
errors++;
//Before we exit, reset the 'BEING_CRACKED' to zero
for (i=0; i < numbytes_to_recover; i++){
for (i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] &= 0xFF;
keytable[bytes_to_recover[i]] |= CRACK_FAILED;
}
} else {
//PrintAndLogDevice(SUCCESS, "DES calcs: %u", brute);
for (i=0; i < numbytes_to_recover; i++){
for (i = 0; i < numbytes_to_recover; i++) {
keytable[bytes_to_recover[i]] &= 0xFF;
keytable[bytes_to_recover[i]] |= CRACKED;
}
@@ -430,7 +443,8 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) {
* @param master_key where to put the master key
* @return 0 for ok, 1 for failz
*/
int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){
int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[])
{
mbedtls_des_context ctx_e;
uint8_t z_0[8] = {0};
@@ -441,8 +455,8 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){
uint8_t result[8] = {0};
// y_0 and z_0 are the first 16 bytes of the keytable
memcpy(y_0, first16bytes,8);
memcpy(z_0, first16bytes+8,8);
memcpy(y_0, first16bytes, 8);
memcpy(z_0, first16bytes + 8, 8);
// Our DES-implementation uses the standard NIST
// format for keys, thus must translate from iclass
@@ -450,7 +464,7 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){
permutekey_rev(z_0, z_0_rev);
// ~K_cus = DESenc(z[0], y[0])
mbedtls_des_setkey_enc( &ctx_e, z_0_rev );
mbedtls_des_setkey_enc(&ctx_e, z_0_rev);
mbedtls_des_crypt_ecb(&ctx_e, y_0, key64_negated);
int i;
@@ -462,20 +476,22 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){
uint8_t key64_stdformat[8] = {0};
permutekey_rev(key64, key64_stdformat);
mbedtls_des_setkey_enc( &ctx_e, key64_stdformat );
mbedtls_des_setkey_enc(&ctx_e, key64_stdformat);
mbedtls_des_crypt_ecb(&ctx_e, key64_negated, result);
PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(SUCCESS, "-- High security custom key (Kcus) --");
PrintAndLogDevice(NORMAL, "\n");
PrintAndLogDevice(SUCCESS, "-- High security custom key (Kcus) --");
printvar("[+] Standard format ", key64_stdformat, 8);
printvar("[+] iClass format ", key64, 8);
if (master_key != NULL)
memcpy(master_key, key64, 8);
if (memcmp(z_0,result,4) != 0) {
if (memcmp(z_0, result, 4) != 0) {
PrintAndLogDevice(WARNING, "Failed to verify calculated master key (k_cus)! Something is wrong.");
return 1;
} else {
PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(SUCCESS, "Key verified ok!\n");
PrintAndLogDevice(NORMAL, "\n");
PrintAndLogDevice(SUCCESS, "Key verified ok!\n");
}
return 0;
}
@@ -486,22 +502,23 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){
* @param keytable
* @return
*/
int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) {
int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[])
{
uint8_t i;
int errors = 0;
size_t itemsize = sizeof(dumpdata);
uint64_t t1 = msclock();
dumpdata* attack = (dumpdata* ) calloc(itemsize, sizeof(uint8_t));
dumpdata *attack = (dumpdata *) calloc(itemsize, sizeof(uint8_t));
for (i = 0 ; i * itemsize < dumpsize ; i++ ) {
for (i = 0 ; i * itemsize < dumpsize ; i++) {
memcpy(attack, dump + i * itemsize, itemsize);
errors += bruteforceItem(*attack, keytable);
}
free(attack);
PrintAndLogDevice(SUCCESS, "time: %" PRIu64 " seconds", (msclock()-t1)/1000);
PrintAndLogDevice(SUCCESS, "time: %" PRIu64 " seconds", (msclock() - t1) / 1000);
// Pick out the first 16 bytes of the keytable.
// The keytable is now in 16-bit ints, where the upper 8 bits
@@ -525,7 +542,8 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) {
* @param filename
* @return
*/
int bruteforceFile(const char *filename, uint16_t keytable[]) {
int bruteforceFile(const char *filename, uint16_t keytable[])
{
FILE *f = fopen(filename, "rb");
if (!f) {
PrintAndLogDevice(WARNING, "Failed to read from file '%s'", filename);
@@ -543,7 +561,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[]) {
}
uint8_t *dump = calloc(fsize, sizeof(uint8_t));
if ( !dump ) {
if (!dump) {
PrintAndLogDevice(WARNING, "Failed to allocate memory");
fclose(f);
return 2;
@@ -553,7 +571,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[]) {
fclose(f);
if (bytes_read < fsize) {
PrintAndLogDevice(WARNING, "Error, could only read %d bytes (should be %d)", bytes_read, fsize );
PrintAndLogDevice(WARNING, "Error, could only read %d bytes (should be %d)", bytes_read, fsize);
}
uint8_t res = bruteforceDump(dump, fsize, keytable);
@@ -566,7 +584,8 @@ int bruteforceFile(const char *filename, uint16_t keytable[]) {
* @param filename
* @return
*/
int bruteforceFileNoKeys(const char *filename) {
int bruteforceFileNoKeys(const char *filename)
{
uint16_t keytable[128] = {0};
return bruteforceFile(filename, keytable);
}
@@ -577,7 +596,8 @@ int bruteforceFileNoKeys(const char *filename) {
// ----------------------------------------------------------------------------
// TEST CODE BELOW
// ----------------------------------------------------------------------------
int _testBruteforce() {
int _testBruteforce()
{
int errors = 0;
if (true) {
// First test
@@ -601,11 +621,11 @@ int _testBruteforce() {
uint16_t keytable[128] = {0};
//Test a few variants
if (fileExists("iclass_dump.bin")){
if (fileExists("iclass_dump.bin")) {
errors |= bruteforceFile("iclass_dump.bin", keytable);
} else if (fileExists("loclass/iclass_dump.bin")){
} else if (fileExists("loclass/iclass_dump.bin")) {
errors |= bruteforceFile("loclass/iclass_dump.bin", keytable);
} else if (fileExists("client/loclass/iclass_dump.bin")){
} else if (fileExists("client/loclass/iclass_dump.bin")) {
errors |= bruteforceFile("client/loclass/iclass_dump.bin", keytable);
} else {
PrintAndLogDevice(WARNING, "Error: The file iclass_dump.bin was not found!");
@@ -614,15 +634,16 @@ int _testBruteforce() {
return errors;
}
int _test_iclass_key_permutation() {
uint8_t testcase[8] = {0x6c,0x8d,0x44,0xf9,0x2a,0x2d,0x01,0xbf};
int _test_iclass_key_permutation()
{
uint8_t testcase[8] = {0x6c, 0x8d, 0x44, 0xf9, 0x2a, 0x2d, 0x01, 0xbf};
uint8_t testcase_output[8] = {0};
uint8_t testcase_output_correct[8] = {0x8a,0x0d,0xb9,0x88,0xbb,0xa7,0x90,0xea};
uint8_t testcase_output_correct[8] = {0x8a, 0x0d, 0xb9, 0x88, 0xbb, 0xa7, 0x90, 0xea};
uint8_t testcase_output_rev[8] = {0};
permutekey(testcase, testcase_output);
permutekey_rev(testcase_output, testcase_output_rev);
if (memcmp(testcase_output, testcase_output_correct,8) != 0) {
if (memcmp(testcase_output, testcase_output_correct, 8) != 0) {
PrintAndLogDevice(WARNING, "Error with iclass key permute!");
printarr("testcase_output", testcase_output, 8);
printarr("testcase_output_correct", testcase_output_correct, 8);
@@ -640,13 +661,14 @@ int _test_iclass_key_permutation() {
return 0;
}
int _testHash1() {
uint8_t expected[8] = {0x7E,0x72,0x2F,0x40,0x2D,0x02,0x51,0x42};
uint8_t csn[8] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0};
int _testHash1()
{
uint8_t expected[8] = {0x7E, 0x72, 0x2F, 0x40, 0x2D, 0x02, 0x51, 0x42};
uint8_t csn[8] = {0x01, 0x02, 0x03, 0x04, 0xF7, 0xFF, 0x12, 0xE0};
uint8_t k[8] = {0};
hash1(csn, k);
if (memcmp(k,expected,8) != 0) {
if (memcmp(k, expected, 8) != 0) {
PrintAndLogDevice(WARNING, "Error with hash1!");
printarr("calculated", k, 8);
printarr("expected", expected, 8);
@@ -655,25 +677,26 @@ int _testHash1() {
return 0;
}
int testElite() {
int testElite()
{
PrintAndLogDevice(INFO, "Testing iClass Elite functinality...");
PrintAndLogDevice(INFO, "Testing hash2");
uint8_t k_cus[8] = {0x5B,0x7C,0x62,0xC4,0x91,0xC1,0x1B,0x39};
uint8_t k_cus[8] = {0x5B, 0x7C, 0x62, 0xC4, 0x91, 0xC1, 0x1B, 0x39};
/**
*Expected:
* High Security Key Table
00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
*/
uint8_t keytable[128] = {0};
hash2(k_cus, keytable);
@@ -686,7 +709,7 @@ int testElite() {
PrintAndLogDevice(INFO, "Testing hash1...");
errors += _testHash1();
PrintAndLogDevice(INFO, "Testing key diversification ...");
errors +=_test_iclass_key_permutation();
errors += _test_iclass_key_permutation();
errors += _testBruteforce();
return errors;
}

View File

@@ -104,7 +104,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]);
* @param csn the CSN used
* @param k output
*/
void hash1(uint8_t csn[] , uint8_t k[]);
void hash1(uint8_t csn[], uint8_t k[]);
void hash2(uint8_t *key64, uint8_t *outp_keytable);
/**
* From dismantling iclass-paper:
@@ -118,7 +118,7 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable);
* @param master_key where to put the master key
* @return 0 for ok, 1 for failz
*/
int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] );
int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]);
/**
* @brief Test function

View File

@@ -45,7 +45,8 @@
* @param filename
* @return
*/
int fileExists(const char *filename) {
int fileExists(const char *filename)
{
#ifdef _WIN32
struct _stat st;
@@ -57,13 +58,14 @@ int fileExists(const char *filename) {
return result == 0;
}
int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen) {
int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen)
{
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
char *fileName = calloc(size, sizeof(char));
int num = 1;
sprintf(fileName,"%s.%s", preferredName, suffix);
sprintf(fileName, "%s.%s", preferredName, suffix);
while (fileExists(fileName)) {
sprintf(fileName,"%s-%d.%s", preferredName, num, suffix);
sprintf(fileName, "%s-%d.%s", preferredName, num, suffix);
num++;
}
/* We should have a valid filename now, e.g. dumpdata-3.bin */
@@ -71,34 +73,35 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
/*Opening file for writing in binary mode*/
FILE *f = fopen(fileName, "wb");
if (!f) {
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_( % s)"'", fileName);
free(fileName);
return 1;
}
fwrite(data, 1, datalen, f);
fflush(f);
fclose(f);
PrintAndLogDevice(SUCCESS, "saved %u bytes to binary file " _YELLOW_(%s), datalen, fileName);
PrintAndLogDevice(SUCCESS, "saved %u bytes to binary file " _YELLOW_( % s), datalen, fileName);
free(fileName);
return 0;
}
int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen, size_t blocksize) {
int saveFileEML(const char *preferredName, const char *suffix, uint8_t *data, size_t datalen, size_t blocksize)
{
if ( preferredName == NULL ) return 1;
if ( suffix == NULL ) return 1;
if ( data == NULL ) return 1;
if (preferredName == NULL) return 1;
if (suffix == NULL) return 1;
if (data == NULL) return 1;
int retval = 0;
int blocks = datalen/blocksize;
int blocks = datalen / blocksize;
uint16_t currblock = 1;
int i,j;
int i, j;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
char *fileName = calloc(size, sizeof(char));
int num = 1;
sprintf(fileName,"%s.%s", preferredName, suffix);
sprintf(fileName, "%s.%s", preferredName, suffix);
while (fileExists(fileName)) {
sprintf(fileName,"%s-%d.%s", preferredName, num, suffix);
sprintf(fileName, "%s-%d.%s", preferredName, num, suffix);
num++;
}
@@ -107,54 +110,55 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, si
/*Opening file for writing in text mode*/
FILE *f = fopen(fileName, "w+");
if (!f) {
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_( % s)"'", fileName);
retval = 1;
goto out;
}
for (i = 0; i < datalen; i++) {
fprintf(f, "%02X", data[i] );
fprintf(f, "%02X", data[i]);
// no extra line in the end
if ( (i+1) % blocksize == 0 && currblock != blocks ) {
if ((i + 1) % blocksize == 0 && currblock != blocks) {
fprintf(f, "\n");
currblock++;
}
}
// left overs
if ( datalen % blocksize != 0) {
if (datalen % blocksize != 0) {
int index = blocks * blocksize;
for (j = 0; j < datalen % blocksize; j++) {
fprintf(f, "%02X", data[index + j] );
fprintf(f, "%02X", data[index + j]);
}
}
fflush(f);
fclose(f);
PrintAndLogDevice(SUCCESS, "saved %d blocks to text file " _YELLOW_(%s), blocks, fileName);
PrintAndLogDevice(SUCCESS, "saved %d blocks to text file " _YELLOW_( % s), blocks, fileName);
out:
free(fileName);
return retval;
}
int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t* data, size_t datalen) {
if ( preferredName == NULL ) return 1;
if ( suffix == NULL ) return 1;
if ( data == NULL ) return 1;
int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t *data, size_t datalen)
{
if (preferredName == NULL) return 1;
if (suffix == NULL) return 1;
if (data == NULL) return 1;
int retval = 0;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
char *fileName = calloc(size, sizeof(char));
int num = 1;
sprintf(fileName,"%s.%s", preferredName, suffix);
sprintf(fileName, "%s.%s", preferredName, suffix);
while (fileExists(fileName)) {
sprintf(fileName,"%s-%d.%s", preferredName, num, suffix);
sprintf(fileName, "%s-%d.%s", preferredName, num, suffix);
num++;
}
json_t *root = json_object();
JsonSaveStr(root, "Created", "proxmark3");
switch(ftype) {
switch (ftype) {
case jsfRaw:
JsonSaveStr(root, "FileType", "raw");
JsonSaveBufAsHexCompact(root, "raw", data, datalen);
@@ -211,11 +215,11 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
case jsfMfuMemory:
JsonSaveStr(root, "FileType", "mfu");
mfu_dump_t* tmp = (mfu_dump_t*)data;
mfu_dump_t *tmp = (mfu_dump_t *)data;
uint8_t uid[7] = {0};
memcpy(uid, tmp->data, 3);
memcpy(uid+3, tmp->data+4, 4);
memcpy(uid + 3, tmp->data + 4, 4);
JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid));
JsonSaveBufAsHexCompact(root, "$.Card.Version", tmp->version, sizeof(tmp->version));
@@ -235,17 +239,17 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
sprintf(path, "$.blocks.%d", i);
JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4);
}
break;
break;
}
int res = json_dump_file(root, fileName, JSON_INDENT(2));
if (res) {
PrintAndLogDevice(FAILED, "error: can't save the file: " _YELLOW_(%s), fileName);
PrintAndLogDevice(FAILED, "error: can't save the file: " _YELLOW_( % s), fileName);
json_decref(root);
retval = 200;
goto out;
}
PrintAndLogDevice(SUCCESS, "saved to json file " _YELLOW_(%s), fileName);
PrintAndLogDevice(SUCCESS, "saved to json file " _YELLOW_( % s), fileName);
json_decref(root);
out:
@@ -253,20 +257,21 @@ out:
return retval;
}
int loadFile(const char *preferredName, const char *suffix, void* data, size_t* datalen) {
int loadFile(const char *preferredName, const char *suffix, void *data, size_t *datalen)
{
if ( preferredName == NULL ) return 1;
if ( suffix == NULL ) return 1;
if ( data == NULL ) return 1;
if (preferredName == NULL) return 1;
if (suffix == NULL) return 1;
if (data == NULL) return 1;
int retval = 0;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
sprintf(fileName,"%s.%s", preferredName, suffix);
char *fileName = calloc(size, sizeof(char));
sprintf(fileName, "%s.%s", preferredName, suffix);
FILE *f = fopen(fileName, "rb");
if ( !f ) {
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
if (!f) {
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_( % s)"'", fileName);
free(fileName);
return 1;
}
@@ -276,14 +281,14 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t*
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
if ( fsize < 0 ) {
if (fsize < 0) {
PrintAndLogDevice(FAILED, "error, when getting filesize");
retval = 1;
goto out;
}
uint8_t *dump = calloc(fsize, sizeof(uint8_t));
if ( !dump ) {
if (!dump) {
PrintAndLogDevice(FAILED, "error, cannot allocate memory");
retval = 2;
goto out;
@@ -291,17 +296,17 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t*
size_t bytes_read = fread(dump, 1, fsize, f);
if ( bytes_read != fsize ) {
if (bytes_read != fsize) {
PrintAndLogDevice(FAILED, "error, bytes read mismatch file size");
free(dump);
retval = 3;
goto out;
}
memcpy( (data), dump, bytes_read);
memcpy((data), dump, bytes_read);
free(dump);
PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file " _YELLOW_(%s), bytes_read, fileName);
PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file " _YELLOW_( % s), bytes_read, fileName);
*datalen = bytes_read;
@@ -312,21 +317,22 @@ out:
return retval;
}
int loadFileEML(const char *preferredName, const char *suffix, void* data, size_t* datalen) {
int loadFileEML(const char *preferredName, const char *suffix, void *data, size_t *datalen)
{
if ( preferredName == NULL ) return 1;
if ( suffix == NULL ) return 1;
if ( data == NULL ) return 1;
if (preferredName == NULL) return 1;
if (suffix == NULL) return 1;
if (data == NULL) return 1;
size_t counter = 0;
int retval = 0, hexlen = 0;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
sprintf(fileName,"%s.%s", preferredName, suffix);
char *fileName = calloc(size, sizeof(char));
sprintf(fileName, "%s.%s", preferredName, suffix);
FILE *f = fopen(fileName, "r");
if ( !f ) {
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
if (!f) {
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_( % s)"'", fileName);
retval = 1;
goto out;
}
@@ -336,18 +342,18 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_
memset(line, 0, sizeof(line));
uint8_t buf[64] = {0x00};
while ( !feof(f) ) {
while (!feof(f)) {
memset(line, 0, sizeof(line));
if (fgets(line, sizeof(line), f) == NULL){
if (fgets(line, sizeof(line), f) == NULL) {
fclose(f);
PrintAndLogEx(FAILED, "File reading error.");
retval = 2;
goto out;
}
if ( line[0] == '#' )
if (line[0] == '#')
continue;
int res = param_gethex_to_eol(line, 0, buf, sizeof(buf), &hexlen);
@@ -357,9 +363,9 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_
}
}
fclose(f);
PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file " _YELLOW_(%s), counter, fileName);
PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file " _YELLOW_( % s), counter, fileName);
if ( datalen )
if (datalen)
*datalen = counter;
out:
@@ -367,11 +373,12 @@ out:
return retval;
}
int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen) {
int loadFileJSON(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen)
{
if ( preferredName == NULL ) return 1;
if ( suffix == NULL ) return 1;
if ( data == NULL ) return 1;
if (preferredName == NULL) return 1;
if (suffix == NULL) return 1;
if (data == NULL) return 1;
*datalen = 0;
json_t *root;
@@ -379,18 +386,18 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size
int retval = 0;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
sprintf(fileName,"%s.%s", preferredName, suffix);
char *fileName = calloc(size, sizeof(char));
sprintf(fileName, "%s.%s", preferredName, suffix);
root = json_load_file(fileName, 0, &error);
if (!root) {
PrintAndLog("ERROR: json " _YELLOW_(%s) " error on line %d: %s", fileName, error.line, error.text);
PrintAndLog("ERROR: json " _YELLOW_( % s) " error on line %d: %s", fileName, error.line, error.text);
retval = 2;
goto out;
}
if (!json_is_object(root)) {
PrintAndLog("ERROR: Invalid json " _YELLOW_(%s) " format. root must be an object.", fileName);
PrintAndLog("ERROR: Invalid json " _YELLOW_( % s) " format. root must be an object.", fileName);
retval = 3;
goto out;
}
@@ -448,18 +455,19 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size
}
PrintAndLog("loaded from JSON file " _YELLOW_(%s), fileName);
PrintAndLog("loaded from JSON file " _YELLOW_( % s), fileName);
out:
json_decref(root);
free(fileName);
return retval;
}
int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data, size_t* datalen, uint8_t keylen, uint16_t* keycnt ) {
int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt)
{
if ( preferredName == NULL ) return 1;
if ( suffix == NULL ) return 1;
if ( data == NULL ) return 1;
if (preferredName == NULL) return 1;
if (suffix == NULL) return 1;
if (data == NULL) return 1;
// t5577 == 4bytes
// mifare == 6 bytes
@@ -477,18 +485,18 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data
size_t counter = 0;
int retval = 0;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
sprintf(fileName,"%s.%s", preferredName, suffix);
char *fileName = calloc(size, sizeof(char));
sprintf(fileName, "%s.%s", preferredName, suffix);
FILE *f = fopen(fileName, "r");
if ( !f ) {
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName);
if (!f) {
PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_( % s)"'", fileName);
retval = 1;
goto out;
}
// read file
while ( fgets(line, sizeof(line), f) ) {
while (fgets(line, sizeof(line), f)) {
// add null terminator
line[keylen] = 0;
@@ -499,11 +507,11 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data
// The line start with # is comment, skip
if( line[0] == '#' )
if (line[0] == '#')
continue;
if (!isxdigit(line[0])){
PrintAndLogEx(FAILED, "file content error. '%s' must include " _BLUE_(%2d) "HEX symbols", line, keylen);
if (!isxdigit(line[0])) {
PrintAndLogEx(FAILED, "file content error. '%s' must include " _BLUE_( % 2d) "HEX symbols", line, keylen);
continue;
}
@@ -515,9 +523,9 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data
counter += (keylen >> 1);
}
fclose(f);
PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file " _YELLOW_(%s), *keycnt, fileName);
PrintAndLogDevice(SUCCESS, "loaded " _GREEN_( % 2d) "keys from dictionary file " _YELLOW_( % s), *keycnt, fileName);
if ( datalen )
if (datalen)
*datalen = counter;
out:
free(fileName);

View File

@@ -70,7 +70,7 @@ int fileExists(const char *filename);
* @param datalen the length of the data
* @return 0 for ok, 1 for failz
*/
extern int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen);
extern int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen);
/**
* @brief Utility function to save data to a textfile (EML). This method takes a preferred name, but if that
@@ -84,7 +84,7 @@ extern int saveFile(const char *preferredName, const char *suffix, const void* d
* @param blocksize the length of one row
* @return 0 for ok, 1 for failz
*/
extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen, size_t blocksize);
extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t *data, size_t datalen, size_t blocksize);
/** STUB
* @brief Utility function to save JSON data to a file. This method takes a preferred name, but if that
@@ -98,7 +98,7 @@ extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t* d
* @param datalen the length of the data
* @return 0 for ok, 1 for failz
*/
extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t* data, size_t datalen);
extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t *data, size_t datalen);
/** STUB
* @brief Utility function to load data from a binary file. This method takes a preferred name.
@@ -110,7 +110,7 @@ extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileT
* @param datalen the number of bytes loaded from file
* @return 0 for ok, 1 for failz
*/
extern int loadFile(const char *preferredName, const char *suffix, void* data, size_t* datalen);
extern int loadFile(const char *preferredName, const char *suffix, void *data, size_t *datalen);
/**
* @brief Utility function to load data from a textfile (EML). This method takes a preferred name.
@@ -122,7 +122,7 @@ extern int loadFile(const char *preferredName, const char *suffix, void* data, s
* @param datalen the number of bytes loaded from file
* @return 0 for ok, 1 for failz
*/
extern int loadFileEML(const char *preferredName, const char *suffix, void* data, size_t* datalen);
extern int loadFileEML(const char *preferredName, const char *suffix, void *data, size_t *datalen);
/**
* @brief Utility function to load data from a JSON textfile. This method takes a preferred name.
@@ -135,7 +135,7 @@ extern int loadFileEML(const char *preferredName, const char *suffix, void* data
* @param datalen the number of bytes loaded from file
* @return 0 for ok, 1 for failz
*/
extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen);
extern int loadFileJSON(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen);
/**
@@ -150,18 +150,18 @@ extern int loadFileJSON(const char *preferredName, const char *suffix, void* dat
* @param keylen the number of bytes a key per row is
* @return 0 for ok, 1 for failz
*/
extern int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data, size_t* datalen, uint8_t keylen, uint16_t* keycnt );
extern int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt);
#define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args)
#else
/**
* Utility function to print to console. This is used consistently within the library instead
* of printf, but it actually only calls printf. The reason to have this method is to
*make it simple to plug this library into proxmark, which has this function already to
* write also to a logfile. When doing so, just point this function to use PrintAndLog
* @param fmt
*/
/**
* Utility function to print to console. This is used consistently within the library instead
* of printf, but it actually only calls printf. The reason to have this method is to
*make it simple to plug this library into proxmark, which has this function already to
* write also to a logfile. When doing so, just point this function to use PrintAndLog
* @param fmt
*/
#define PrintAndLogDevice(level, format, args...) { }

View File

@@ -7,45 +7,46 @@
#include <ctype.h>
#include "elite_crack.h"
void calc_score(uint8_t* csn, uint8_t* k) {
uint8_t score =0 ;
void calc_score(uint8_t *csn, uint8_t *k)
{
uint8_t score = 0 ;
uint8_t i;
uint8_t goodvals[16] = {0};
uint8_t uniq_vals[8] = {0};
memset(goodvals, 0x00, 16);
memset(uniq_vals, 0x00, 8);
uint8_t badval = 0;
int badscore =0;
for ( i=0; i < 8 ; i++) {
int badscore = 0;
for (i = 0; i < 8 ; i++) {
if (k[i] == 0x01) continue;
if (k[i] == 0x00) continue;
if (k[i] == 0x45) continue;
if (k[i] < 16){
if (k[i] < 16) {
goodvals[k[i]] = 1;
}
// if(k[i] ==9 || k[i]==2){
// goodvals[k[i]] = 1;
// }
else if (k[i]>=16){
else if (k[i] >= 16) {
badscore++;
badval = k[i];
}
}
for (i =0; i < 16; i++) {
for (i = 0; i < 16; i++) {
if (goodvals[i]) {
uniq_vals[score] = i;
score +=1;
score += 1;
}
}
if (score >=2 && badscore < 2) {
if (score >= 2 && badscore < 2) {
printf("CSN\t%02x%02x%02x%02x%02x%02x%02x%02x\t%02x %02x %02x %02x %02x %02x %02x %02x\t"
,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]
,k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7]
);
, csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]
, k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7]
);
for (i=0 ; i < score; i++) {
for (i = 0 ; i < score; i++) {
printf("%d,", uniq_vals[i]);
}
printf("\tbadscore: %d (%02x)", badscore, badval);
@@ -53,21 +54,22 @@ void calc_score(uint8_t* csn, uint8_t* k) {
}
}
void brute_hash1(void){
uint16_t a,b,c,d;
uint8_t csn[8] = {0,0,0,0,0xf7,0xff,0x12,0xe0};
uint8_t k[8]= {0,0,0,0,0,0,0,0};
uint8_t testcsn[8] = {0x00,0x0d,0x0f,0xfd,0xf7,0xff,0x12,0xe0} ;
uint8_t testkey[8] = {0x05 ,0x01 ,0x00 ,0x10 ,0x45 ,0x08 ,0x45,0x56} ;
calc_score(testcsn,testkey);
void brute_hash1(void)
{
uint16_t a, b, c, d;
uint8_t csn[8] = {0, 0, 0, 0, 0xf7, 0xff, 0x12, 0xe0};
uint8_t k[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t testcsn[8] = {0x00, 0x0d, 0x0f, 0xfd, 0xf7, 0xff, 0x12, 0xe0} ;
uint8_t testkey[8] = {0x05, 0x01, 0x00, 0x10, 0x45, 0x08, 0x45, 0x56} ;
calc_score(testcsn, testkey);
printf("Brute forcing hashones\n");
//exit(1);
for (a=0; a < 256; a++) {
for (a = 0; a < 256; a++) {
//if(a > 0)printf("%d/256 done...\n", a);
for (b=0; b < 256; b++)
for (c=0; c < 256; c++)
for (d=0; d < 256; d++) {
for (b = 0; b < 256; b++)
for (c = 0; c < 256; c++)
for (d = 0; d < 256; d++) {
csn[0] = a;
csn[1] = b;
csn[2] = c;
@@ -77,8 +79,8 @@ void brute_hash1(void){
csn[6] = 0x12;
csn[7] = 0xe0;
hash1(csn, k);
calc_score(csn,k);
}
calc_score(csn, k);
}
}
}

View File

@@ -67,7 +67,7 @@ From "Dismantling iclass":
#include "cipherutils.h"
#include "mbedtls/des.h"
uint8_t pi[35] = {0x0F,0x17,0x1B,0x1D,0x1E,0x27,0x2B,0x2D,0x2E,0x33,0x35,0x39,0x36,0x3A,0x3C,0x47,0x4B,0x4D,0x4E,0x53,0x55,0x56,0x59,0x5A,0x5C,0x63,0x65,0x66,0x69,0x6A,0x6C,0x71,0x72,0x74,0x78};
uint8_t pi[35] = {0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D, 0x2E, 0x33, 0x35, 0x39, 0x36, 0x3A, 0x3C, 0x47, 0x4B, 0x4D, 0x4E, 0x53, 0x55, 0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x69, 0x6A, 0x6C, 0x71, 0x72, 0x74, 0x78};
static mbedtls_des_context ctx_enc;
static mbedtls_des_context ctx_dec;
@@ -87,7 +87,7 @@ static int debug_print = 0;
*/
uint8_t getSixBitByte(uint64_t c, int n)
{
return (c >> (42-6*n)) & 0x3F;
return (c >> (42 - 6 * n)) & 0x3F;
}
/**
@@ -104,8 +104,8 @@ void pushbackSixBitByte(uint64_t *c, uint8_t z, int n)
uint64_t masked = z & 0x3F;
uint64_t eraser = 0x3F;
masked <<= 42-6*n;
eraser <<= 42-6*n;
masked <<= 42 - 6 * n;
eraser <<= 42 - 6 * n;
//masked <<= 6*n;
//eraser <<= 6*n;
@@ -125,14 +125,14 @@ void pushbackSixBitByte(uint64_t *c, uint8_t z, int n)
uint64_t swapZvalues(uint64_t c)
{
uint64_t newz = 0;
pushbackSixBitByte(&newz, getSixBitByte(c,0),7);
pushbackSixBitByte(&newz, getSixBitByte(c,1),6);
pushbackSixBitByte(&newz, getSixBitByte(c,2),5);
pushbackSixBitByte(&newz, getSixBitByte(c,3),4);
pushbackSixBitByte(&newz, getSixBitByte(c,4),3);
pushbackSixBitByte(&newz, getSixBitByte(c,5),2);
pushbackSixBitByte(&newz, getSixBitByte(c,6),1);
pushbackSixBitByte(&newz, getSixBitByte(c,7),0);
pushbackSixBitByte(&newz, getSixBitByte(c, 0), 7);
pushbackSixBitByte(&newz, getSixBitByte(c, 1), 6);
pushbackSixBitByte(&newz, getSixBitByte(c, 2), 5);
pushbackSixBitByte(&newz, getSixBitByte(c, 3), 4);
pushbackSixBitByte(&newz, getSixBitByte(c, 4), 3);
pushbackSixBitByte(&newz, getSixBitByte(c, 5), 2);
pushbackSixBitByte(&newz, getSixBitByte(c, 6), 1);
pushbackSixBitByte(&newz, getSixBitByte(c, 7), 0);
newz |= (c & 0xFFFF000000000000);
return newz;
}
@@ -145,26 +145,25 @@ uint64_t ck(int i, int j, uint64_t z)
if (i == 1 && j == -1) {
// ck(1, 1, z [0] . . . z [3] ) = z [0] . . . z [3]
return z;
} else if( j == -1) {
} else if (j == -1) {
// ck(i, 1, z [0] . . . z [3] ) = ck(i 1, i 2, z [0] . . . z [3] )
return ck(i-1,i-2, z);
return ck(i - 1, i - 2, z);
}
if (getSixBitByte(z,i) == getSixBitByte(z,j))
{
if (getSixBitByte(z, i) == getSixBitByte(z, j)) {
//ck(i, j 1, z [0] . . . z [i] ← j . . . z [3] )
uint64_t newz = 0;
int c;
for(c = 0; c < 4; c++) {
uint8_t val = getSixBitByte(z,c);
for (c = 0; c < 4; c++) {
uint8_t val = getSixBitByte(z, c);
if (c == i)
pushbackSixBitByte(&newz, j, c);
else
pushbackSixBitByte(&newz, val, c);
}
return ck(i,j-1,newz);
return ck(i, j - 1, newz);
} else {
return ck(i,j-1,z);
return ck(i, j - 1, z);
}
}
/**
@@ -189,10 +188,10 @@ uint64_t check(uint64_t z)
//These 64 bits are divided as c = x, y, z [0] , . . . , z [7]
// ck(3, 2, z [0] . . . z [3] )
uint64_t ck1 = ck(3,2, z );
uint64_t ck1 = ck(3, 2, z);
// ck(3, 2, z [4] . . . z [7] )
uint64_t ck2 = ck(3,2, z << 24);
uint64_t ck2 = ck(3, 2, z << 24);
//The ck function will place the values
// in the middle of z.
@@ -203,45 +202,44 @@ uint64_t check(uint64_t z)
}
void permute(BitstreamIn *p_in, uint64_t z,int l,int r, BitstreamOut* out)
void permute(BitstreamIn *p_in, uint64_t z, int l, int r, BitstreamOut *out)
{
if(bitsLeft(p_in) == 0)
if (bitsLeft(p_in) == 0)
return;
bool pn = tailBit(p_in);
if( pn ) // pn = 1
{
uint8_t zl = getSixBitByte(z,l);
if (pn) { // pn = 1
uint8_t zl = getSixBitByte(z, l);
push6bits(out, zl+1);
permute(p_in, z, l+1,r, out);
}else // otherwise
{
uint8_t zr = getSixBitByte(z,r);
push6bits(out, zl + 1);
permute(p_in, z, l + 1, r, out);
} else { // otherwise
uint8_t zr = getSixBitByte(z, r);
push6bits(out, zr);
permute(p_in,z,l,r+1,out);
permute(p_in, z, l, r + 1, out);
}
}
void printbegin() {
void printbegin()
{
if (debug_print < 2)
return;
PrintAndLogDevice(NORMAL, " | x| y|z0|z1|z2|z3|z4|z5|z6|z7|");
}
void printState(char* desc, uint64_t c)
void printState(char *desc, uint64_t c)
{
if(debug_print < 2)
if (debug_print < 2)
return;
printf("%s : ", desc);
uint8_t x = (c & 0xFF00000000000000 ) >> 56;
uint8_t y = (c & 0x00FF000000000000 ) >> 48;
printf(" %02x %02x", x,y);
uint8_t x = (c & 0xFF00000000000000) >> 56;
uint8_t y = (c & 0x00FF000000000000) >> 48;
printf(" %02x %02x", x, y);
int i;
for(i = 0; i < 8; i++)
printf(" %02x", getSixBitByte(c,i));
for (i = 0; i < 8; i++)
printf(" %02x", getSixBitByte(c, i));
printf("\n");
}
@@ -261,61 +259,59 @@ void hash0(uint64_t c, uint8_t k[8])
c = swapZvalues(c);
printbegin();
printState("origin",c);
printState("origin", c);
//These 64 bits are divided as c = x, y, z [0] , . . . , z [7]
// x = 8 bits
// y = 8 bits
// z0-z7 6 bits each : 48 bits
uint8_t x = (c & 0xFF00000000000000 ) >> 56;
uint8_t y = (c & 0x00FF000000000000 ) >> 48;
uint8_t x = (c & 0xFF00000000000000) >> 56;
uint8_t y = (c & 0x00FF000000000000) >> 48;
int n;
uint8_t zn, zn4, _zn, _zn4;
uint64_t zP = 0;
for(n = 0; n < 4 ; n++)
{
zn = getSixBitByte(c,n);
for (n = 0; n < 4 ; n++) {
zn = getSixBitByte(c, n);
zn4 = getSixBitByte(c,n+4);
zn4 = getSixBitByte(c, n + 4);
_zn = (zn % (63-n)) + n;
_zn4 = (zn4 % (64-n)) + n;
_zn = (zn % (63 - n)) + n;
_zn4 = (zn4 % (64 - n)) + n;
pushbackSixBitByte(&zP, _zn,n);
pushbackSixBitByte(&zP, _zn4,n+4);
pushbackSixBitByte(&zP, _zn, n);
pushbackSixBitByte(&zP, _zn4, n + 4);
}
printState("0|0|z'",zP);
printState("0|0|z'", zP);
uint64_t zCaret = check(zP);
printState("0|0|z^",zP);
printState("0|0|z^", zP);
uint8_t p = pi[x % 35];
if(x & 1) //Check if x7 is 1
if (x & 1) //Check if x7 is 1
p = ~p;
if(debug_print >= 2) PrintAndLogDevice(DEBUG, "p:%02x", p);
if (debug_print >= 2) PrintAndLogDevice(DEBUG, "p:%02x", p);
BitstreamIn p_in = { &p, 8,0 };
uint8_t outbuffer[] = {0,0,0,0,0,0,0,0};
BitstreamOut out = {outbuffer,0,0};
permute(&p_in,zCaret,0,4,&out);//returns 48 bits? or 6 8-bytes
BitstreamIn p_in = { &p, 8, 0 };
uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamOut out = {outbuffer, 0, 0};
permute(&p_in, zCaret, 0, 4, &out); //returns 48 bits? or 6 8-bytes
//Out is now a buffer containing six-bit bytes, should be 48 bits
// if all went well
//Shift z-values down onto the lower segment
uint64_t zTilde = x_bytes_to_num(outbuffer,8);
uint64_t zTilde = x_bytes_to_num(outbuffer, 8);
zTilde >>= 16;
printState("0|0|z~", zTilde);
int i;
int zerocounter =0 ;
for(i = 0; i < 8; i++)
{
int zerocounter = 0 ;
for (i = 0; i < 8; i++) {
// the key on index i is first a bit from y
// then six bits from z,
// then a bit from p
@@ -326,7 +322,7 @@ void hash0(uint64_t c, uint8_t k[8])
//k[i] |= (y << i) & 0x80 ;
// First, place y(7-i) leftmost in k
k[i] |= (y << (7-i)) & 0x80 ;
k[i] |= (y << (7 - i)) & 0x80 ;
@@ -343,20 +339,17 @@ void hash0(uint64_t c, uint8_t k[8])
//Shift bit i into rightmost location (mask only after complement)
uint8_t p_i = p >> i & 0x1;
if( k[i] )// yi = 1
{
if (k[i]) { // yi = 1
//printf("k[%d] +1\n", i);
k[i] |= ~zTilde_i & 0x7E;
k[i] |= p_i & 1;
k[i] += 1;
}else // otherwise
{
} else { // otherwise
k[i] |= zTilde_i & 0x7E;
k[i] |= (~p_i) & 1;
}
if ((k[i] & 1 )== 0)
{
if ((k[i] & 1) == 0) {
zerocounter++;
}
}
@@ -370,31 +363,31 @@ void hash0(uint64_t c, uint8_t k[8])
void diversifyKey(uint8_t csn[8], uint8_t key[8], uint8_t div_key[8])
{
// Prepare the DES key
mbedtls_des_setkey_enc( &ctx_enc, key);
mbedtls_des_setkey_enc(&ctx_enc, key);
uint8_t crypted_csn[8] = {0};
// Calculate DES(CSN, KEY)
mbedtls_des_crypt_ecb(&ctx_enc,csn, crypted_csn);
mbedtls_des_crypt_ecb(&ctx_enc, csn, crypted_csn);
//Calculate HASH0(DES))
uint64_t crypt_csn = x_bytes_to_num(crypted_csn, 8);
//uint64_t crypted_csn_swapped = swapZvalues(crypt_csn);
hash0(crypt_csn,div_key);
hash0(crypt_csn, div_key);
}
void testPermute()
{
uint64_t x = 0;
pushbackSixBitByte(&x,0x00,0);
pushbackSixBitByte(&x,0x01,1);
pushbackSixBitByte(&x,0x02,2);
pushbackSixBitByte(&x,0x03,3);
pushbackSixBitByte(&x,0x04,4);
pushbackSixBitByte(&x,0x05,5);
pushbackSixBitByte(&x,0x06,6);
pushbackSixBitByte(&x,0x07,7);
pushbackSixBitByte(&x, 0x00, 0);
pushbackSixBitByte(&x, 0x01, 1);
pushbackSixBitByte(&x, 0x02, 2);
pushbackSixBitByte(&x, 0x03, 3);
pushbackSixBitByte(&x, 0x04, 4);
pushbackSixBitByte(&x, 0x05, 5);
pushbackSixBitByte(&x, 0x06, 6);
pushbackSixBitByte(&x, 0x07, 7);
uint8_t mres[8] = { getSixBitByte(x, 0),
getSixBitByte(x, 1),
@@ -403,35 +396,36 @@ void testPermute()
getSixBitByte(x, 4),
getSixBitByte(x, 5),
getSixBitByte(x, 6),
getSixBitByte(x, 7)};
printarr("input_perm", mres,8);
getSixBitByte(x, 7)
};
printarr("input_perm", mres, 8);
uint8_t p = ~pi[0];
BitstreamIn p_in = { &p, 8,0 };
uint8_t outbuffer[] = {0,0,0,0,0,0,0,0};
BitstreamOut out = {outbuffer,0,0};
BitstreamIn p_in = { &p, 8, 0 };
uint8_t outbuffer[] = {0, 0, 0, 0, 0, 0, 0, 0};
BitstreamOut out = {outbuffer, 0, 0};
permute(&p_in, x,0,4, &out);
permute(&p_in, x, 0, 4, &out);
uint64_t permuted = x_bytes_to_num(outbuffer,8);
uint64_t permuted = x_bytes_to_num(outbuffer, 8);
//printf("zTilde 0x%"PRIX64"\n", zTilde);
permuted >>= 16;
uint8_t res[8] = { getSixBitByte(permuted, 0),
getSixBitByte(permuted, 1),
getSixBitByte(permuted, 2),
getSixBitByte(permuted, 3),
getSixBitByte(permuted, 4),
getSixBitByte(permuted, 5),
getSixBitByte(permuted, 6),
getSixBitByte(permuted, 7)};
getSixBitByte(permuted, 1),
getSixBitByte(permuted, 2),
getSixBitByte(permuted, 3),
getSixBitByte(permuted, 4),
getSixBitByte(permuted, 5),
getSixBitByte(permuted, 6),
getSixBitByte(permuted, 7)
};
printarr("permuted", res, 8);
}
// These testcases are
// { UID , TEMP_KEY, DIV_KEY} using the specific key
typedef struct
{
typedef struct {
uint8_t uid[8];
uint8_t t_key[8];
uint8_t div_key[8];
@@ -460,14 +454,14 @@ int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_context
printarr("Expected", testcase.t_key, 8);
retval = 1;
}
uint64_t crypted_csn = x_bytes_to_num(des_encrypted_csn,8);
uint64_t crypted_csn = x_bytes_to_num(des_encrypted_csn, 8);
hash0(crypted_csn, div_key);
if (memcmp(div_key, testcase.div_key, 8) != 0) {
//Key diversification fail
PrintAndLogDevice(FAILED, "Div key != expected result");
printarr(" csn ", testcase.uid,8);
printarr("{csn} ", des_encrypted_csn,8);
printarr(" csn ", testcase.uid, 8);
printarr("{csn} ", des_encrypted_csn, 8);
printarr("hash0 ", div_key, 8);
printarr("Expected", testcase.div_key, 8);
retval = 1;
@@ -475,15 +469,17 @@ int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_context
return retval;
}
bool des_getParityBitFromKey(uint8_t key)
{ // The top 7 bits is used
{
// The top 7 bits is used
bool parity = ((key & 0x80) >> 7)
^ ((key & 0x40) >> 6) ^ ((key & 0x20) >> 5)
^ ((key & 0x10) >> 4) ^ ((key & 0x08) >> 3)
^ ((key & 0x04) >> 2) ^ ((key & 0x02) >> 1);
^ ((key & 0x40) >> 6) ^ ((key & 0x20) >> 5)
^ ((key & 0x10) >> 4) ^ ((key & 0x08) >> 3)
^ ((key & 0x04) >> 2) ^ ((key & 0x02) >> 1);
return !parity;
}
void des_checkParity(uint8_t* key) {
void des_checkParity(uint8_t *key)
{
int i;
int fails = 0;
for (i = 0; i < 8; i++) {
@@ -500,84 +496,85 @@ void des_checkParity(uint8_t* key) {
}
}
Testcase testcases[] ={
Testcase testcases[] = {
{{0x8B,0xAC,0x60,0x1F,0x53,0xB8,0xED,0x11},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0xAE,0x51,0xE5,0x62,0xE7,0x9A,0x99,0x39},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01},{0x04,0x02,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x9B,0x21,0xE4,0x31,0x6A,0x00,0x29,0x62},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02},{0x06,0x04,0x02,0x08,0x01,0x03,0x05,0x07}},
{{0x65,0x24,0x0C,0x41,0x4F,0xC2,0x21,0x93},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04},{0x0A,0x04,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x7F,0xEB,0xAE,0x93,0xE5,0x30,0x08,0xBD},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08},{0x12,0x04,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x49,0x7B,0x70,0x74,0x9B,0x35,0x1B,0x83},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10},{0x22,0x04,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x02,0x3C,0x15,0x6B,0xED,0xA5,0x64,0x6C},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20},{0x42,0x04,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0xE8,0x37,0xE0,0xE2,0xC6,0x45,0x24,0xF3},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40},{0x02,0x06,0x04,0x08,0x01,0x03,0x05,0x07}},
{{0xAB,0xBD,0x30,0x05,0x29,0xC8,0xF7,0x12},{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},{0x02,0x08,0x06,0x04,0x01,0x03,0x05,0x07}},
{{0x17,0xE8,0x97,0xF0,0x99,0xB6,0x79,0x31},{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00},{0x02,0x0C,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x49,0xA4,0xF0,0x8F,0x5F,0x96,0x83,0x16},{0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00},{0x02,0x14,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x60,0xF5,0x7E,0x54,0xAA,0x41,0x83,0xD4},{0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00},{0x02,0x24,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x1D,0xF6,0x3B,0x6B,0x85,0x55,0xF0,0x4B},{0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00},{0x02,0x44,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x1F,0xDC,0x95,0x1A,0xEA,0x6B,0x4B,0xB4},{0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00},{0x02,0x04,0x08,0x06,0x01,0x03,0x05,0x07}},
{{0xEC,0x93,0x72,0xF0,0x3B,0xA9,0xF5,0x0B},{0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00},{0x02,0x04,0x0A,0x08,0x01,0x03,0x05,0x07}},
{{0xDE,0x57,0x5C,0xBE,0x2D,0x55,0x03,0x12},{0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00},{0x02,0x04,0x0E,0x08,0x01,0x03,0x05,0x07}},
{{0x1E,0xD2,0xB5,0xCE,0x90,0xC9,0xC1,0xCC},{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00},{0x02,0x04,0x16,0x08,0x01,0x03,0x05,0x07}},
{{0xD8,0x65,0x96,0x4E,0xE7,0x74,0x99,0xB8},{0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00},{0x02,0x04,0x26,0x08,0x01,0x03,0x05,0x07}},
{{0xE3,0x7A,0x29,0x83,0x31,0xD5,0x3A,0x54},{0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00},{0x02,0x04,0x46,0x08,0x01,0x03,0x05,0x07}},
{{0x3A,0xB5,0x1A,0x34,0x34,0x25,0x12,0xF0},{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00},{0x02,0x04,0x06,0x0A,0x01,0x03,0x05,0x07}},
{{0xF2,0x88,0xEE,0x6F,0x70,0x6F,0xC2,0x52},{0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00},{0x02,0x04,0x06,0x0C,0x01,0x03,0x05,0x07}},
{{0x76,0xEF,0xEB,0x80,0x52,0x43,0x83,0x57},{0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00},{0x02,0x04,0x06,0x10,0x01,0x03,0x05,0x07}},
{{0x1C,0x09,0x8E,0x3B,0x23,0x23,0x52,0xB5},{0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00},{0x02,0x04,0x06,0x18,0x01,0x03,0x05,0x07}},
{{0xA9,0x13,0xA2,0xBE,0xCF,0x1A,0xC4,0x9A},{0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00},{0x02,0x04,0x06,0x28,0x01,0x03,0x05,0x07}},
{{0x25,0x56,0x4B,0xB0,0xC8,0x2A,0xD4,0x27},{0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00},{0x02,0x04,0x06,0x48,0x01,0x03,0x05,0x07}},
{{0xB1,0x04,0x57,0x3F,0xA7,0x16,0x62,0xD4},{0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x03,0x01,0x05,0x07}},
{{0x45,0x46,0xED,0xCC,0xE7,0xD3,0x8E,0xA3},{0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x05,0x03,0x01,0x07}},
{{0x22,0x6D,0xB5,0x35,0xE0,0x5A,0xE0,0x90},{0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x09,0x03,0x05,0x07}},
{{0xB8,0xF5,0xE5,0x44,0xC5,0x98,0x4A,0xBD},{0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x11,0x03,0x05,0x07}},
{{0xAC,0x78,0x0A,0x23,0x9E,0xF6,0xBC,0xA0},{0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x21,0x03,0x05,0x07}},
{{0x46,0x6B,0x2D,0x70,0x41,0x17,0xBF,0x3D},{0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x41,0x03,0x05,0x07}},
{{0x64,0x44,0x24,0x71,0xA2,0x56,0xDF,0xB5},{0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x05,0x03,0x07}},
{{0xC4,0x00,0x52,0x24,0xA2,0xD6,0x16,0x7A},{0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x07,0x05,0x03}},
{{0xD8,0x4A,0x80,0x1E,0x95,0x5B,0x70,0xC4},{0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x0B,0x05,0x07}},
{{0x08,0x56,0x6E,0xB5,0x64,0xD6,0x47,0x4E},{0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x13,0x05,0x07}},
{{0x41,0x6F,0xBA,0xA4,0xEB,0xAE,0xA0,0x55},{0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x23,0x05,0x07}},
{{0x62,0x9D,0xDE,0x72,0x84,0x4A,0x53,0xD5},{0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x43,0x05,0x07}},
{{0x39,0xD3,0x2B,0x66,0xB8,0x08,0x40,0x2E},{0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x07,0x05}},
{{0xAF,0x67,0xA9,0x18,0x57,0x21,0xAF,0x8D},{0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x09,0x07}},
{{0x34,0xBC,0x9D,0xBC,0xC4,0xC2,0x3B,0xC8},{0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x0D,0x07}},
{{0xB6,0x50,0xF9,0x81,0xF6,0xBF,0x90,0x3C},{0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x15,0x07}},
{{0x71,0x41,0x93,0xA1,0x59,0x81,0xA5,0x52},{0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x25,0x07}},
{{0x6B,0x00,0xBD,0x74,0x1C,0x3C,0xE0,0x1A},{0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x45,0x07}},
{{0x76,0xFD,0x0B,0xD0,0x41,0xD2,0x82,0x5D},{0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x05,0x09}},
{{0xC6,0x3A,0x1C,0x25,0x63,0x5A,0x2F,0x0E},{0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x05,0x0B}},
{{0xD9,0x0E,0xD7,0x30,0xE2,0xAD,0xA9,0x87},{0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x05,0x0F}},
{{0x6B,0x81,0xC6,0xD1,0x05,0x09,0x87,0x1E},{0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x05,0x17}},
{{0xB4,0xA7,0x1E,0x02,0x54,0x37,0x43,0x35},{0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x05,0x27}},
{{0x45,0x14,0x7C,0x7F,0xE0,0xDE,0x09,0x65},{0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x05,0x47}},
{{0x78,0xB0,0xF5,0x20,0x8B,0x7D,0xF3,0xDD},{0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00},{0xFE,0x04,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x88,0xB3,0x3C,0xE1,0xF7,0x87,0x42,0xA1},{0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0xFC,0x06,0x08,0x01,0x03,0x05,0x07}},
{{0x11,0x2F,0xB2,0xF7,0xE2,0xB2,0x4F,0x6E},{0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0xFA,0x08,0x01,0x03,0x05,0x07}},
{{0x25,0x56,0x4E,0xC6,0xEB,0x2D,0x74,0x5B},{0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0xF8,0x01,0x03,0x05,0x07}},
{{0x7E,0x98,0x37,0xF9,0x80,0x8F,0x09,0x82},{0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0xFF,0x03,0x05,0x07}},
{{0xF9,0xB5,0x62,0x3B,0xD8,0x7B,0x3C,0x3F},{0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0xFD,0x05,0x07}},
{{0x29,0xC5,0x2B,0xFA,0xD1,0xFC,0x5C,0xC7},{0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0xFB,0x07}},
{{0xC1,0xA3,0x09,0x71,0xBD,0x8E,0xAF,0x2F},{0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x06,0x08,0x01,0x03,0x05,0xF9}},
{{0xB6,0xDD,0xD1,0xAD,0xAA,0x15,0x6F,0x29},{0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x01,0x03,0x05,0x02,0x07,0x04,0x06,0x08}},
{{0x65,0x34,0x03,0x19,0x17,0xB3,0xA3,0x96},{0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x01,0x06,0x08,0x03,0x05,0x07}},
{{0xF9,0x38,0x43,0x56,0x52,0xE5,0xB1,0xA9},{0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x01,0x02,0x04,0x06,0x08,0x03,0x05,0x07}},
{{0x8B, 0xAC, 0x60, 0x1F, 0x53, 0xB8, 0xED, 0x11}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0xAE, 0x51, 0xE5, 0x62, 0xE7, 0x9A, 0x99, 0x39}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, {0x04, 0x02, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x9B, 0x21, 0xE4, 0x31, 0x6A, 0x00, 0x29, 0x62}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, {0x06, 0x04, 0x02, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x65, 0x24, 0x0C, 0x41, 0x4F, 0xC2, 0x21, 0x93}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}, {0x0A, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x7F, 0xEB, 0xAE, 0x93, 0xE5, 0x30, 0x08, 0xBD}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, {0x12, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x49, 0x7B, 0x70, 0x74, 0x9B, 0x35, 0x1B, 0x83}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, {0x22, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x02, 0x3C, 0x15, 0x6B, 0xED, 0xA5, 0x64, 0x6C}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20}, {0x42, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0xE8, 0x37, 0xE0, 0xE2, 0xC6, 0x45, 0x24, 0xF3}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}, {0x02, 0x06, 0x04, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0xAB, 0xBD, 0x30, 0x05, 0x29, 0xC8, 0xF7, 0x12}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, {0x02, 0x08, 0x06, 0x04, 0x01, 0x03, 0x05, 0x07}},
{{0x17, 0xE8, 0x97, 0xF0, 0x99, 0xB6, 0x79, 0x31}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, {0x02, 0x0C, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x49, 0xA4, 0xF0, 0x8F, 0x5F, 0x96, 0x83, 0x16}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, {0x02, 0x14, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x60, 0xF5, 0x7E, 0x54, 0xAA, 0x41, 0x83, 0xD4}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00}, {0x02, 0x24, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x1D, 0xF6, 0x3B, 0x6B, 0x85, 0x55, 0xF0, 0x4B}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00}, {0x02, 0x44, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x1F, 0xDC, 0x95, 0x1A, 0xEA, 0x6B, 0x4B, 0xB4}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00}, {0x02, 0x04, 0x08, 0x06, 0x01, 0x03, 0x05, 0x07}},
{{0xEC, 0x93, 0x72, 0xF0, 0x3B, 0xA9, 0xF5, 0x0B}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00}, {0x02, 0x04, 0x0A, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0xDE, 0x57, 0x5C, 0xBE, 0x2D, 0x55, 0x03, 0x12}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00}, {0x02, 0x04, 0x0E, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x1E, 0xD2, 0xB5, 0xCE, 0x90, 0xC9, 0xC1, 0xCC}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00}, {0x02, 0x04, 0x16, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0xD8, 0x65, 0x96, 0x4E, 0xE7, 0x74, 0x99, 0xB8}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, {0x02, 0x04, 0x26, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0xE3, 0x7A, 0x29, 0x83, 0x31, 0xD5, 0x3A, 0x54}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, {0x02, 0x04, 0x46, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x3A, 0xB5, 0x1A, 0x34, 0x34, 0x25, 0x12, 0xF0}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x0A, 0x01, 0x03, 0x05, 0x07}},
{{0xF2, 0x88, 0xEE, 0x6F, 0x70, 0x6F, 0xC2, 0x52}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x0C, 0x01, 0x03, 0x05, 0x07}},
{{0x76, 0xEF, 0xEB, 0x80, 0x52, 0x43, 0x83, 0x57}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x10, 0x01, 0x03, 0x05, 0x07}},
{{0x1C, 0x09, 0x8E, 0x3B, 0x23, 0x23, 0x52, 0xB5}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x18, 0x01, 0x03, 0x05, 0x07}},
{{0xA9, 0x13, 0xA2, 0xBE, 0xCF, 0x1A, 0xC4, 0x9A}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x28, 0x01, 0x03, 0x05, 0x07}},
{{0x25, 0x56, 0x4B, 0xB0, 0xC8, 0x2A, 0xD4, 0x27}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x48, 0x01, 0x03, 0x05, 0x07}},
{{0xB1, 0x04, 0x57, 0x3F, 0xA7, 0x16, 0x62, 0xD4}, {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x03, 0x01, 0x05, 0x07}},
{{0x45, 0x46, 0xED, 0xCC, 0xE7, 0xD3, 0x8E, 0xA3}, {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x05, 0x03, 0x01, 0x07}},
{{0x22, 0x6D, 0xB5, 0x35, 0xE0, 0x5A, 0xE0, 0x90}, {0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x09, 0x03, 0x05, 0x07}},
{{0xB8, 0xF5, 0xE5, 0x44, 0xC5, 0x98, 0x4A, 0xBD}, {0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x11, 0x03, 0x05, 0x07}},
{{0xAC, 0x78, 0x0A, 0x23, 0x9E, 0xF6, 0xBC, 0xA0}, {0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x21, 0x03, 0x05, 0x07}},
{{0x46, 0x6B, 0x2D, 0x70, 0x41, 0x17, 0xBF, 0x3D}, {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x41, 0x03, 0x05, 0x07}},
{{0x64, 0x44, 0x24, 0x71, 0xA2, 0x56, 0xDF, 0xB5}, {0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x05, 0x03, 0x07}},
{{0xC4, 0x00, 0x52, 0x24, 0xA2, 0xD6, 0x16, 0x7A}, {0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x07, 0x05, 0x03}},
{{0xD8, 0x4A, 0x80, 0x1E, 0x95, 0x5B, 0x70, 0xC4}, {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x0B, 0x05, 0x07}},
{{0x08, 0x56, 0x6E, 0xB5, 0x64, 0xD6, 0x47, 0x4E}, {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x13, 0x05, 0x07}},
{{0x41, 0x6F, 0xBA, 0xA4, 0xEB, 0xAE, 0xA0, 0x55}, {0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x23, 0x05, 0x07}},
{{0x62, 0x9D, 0xDE, 0x72, 0x84, 0x4A, 0x53, 0xD5}, {0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x43, 0x05, 0x07}},
{{0x39, 0xD3, 0x2B, 0x66, 0xB8, 0x08, 0x40, 0x2E}, {0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x07, 0x05}},
{{0xAF, 0x67, 0xA9, 0x18, 0x57, 0x21, 0xAF, 0x8D}, {0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x09, 0x07}},
{{0x34, 0xBC, 0x9D, 0xBC, 0xC4, 0xC2, 0x3B, 0xC8}, {0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x0D, 0x07}},
{{0xB6, 0x50, 0xF9, 0x81, 0xF6, 0xBF, 0x90, 0x3C}, {0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x15, 0x07}},
{{0x71, 0x41, 0x93, 0xA1, 0x59, 0x81, 0xA5, 0x52}, {0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x25, 0x07}},
{{0x6B, 0x00, 0xBD, 0x74, 0x1C, 0x3C, 0xE0, 0x1A}, {0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x45, 0x07}},
{{0x76, 0xFD, 0x0B, 0xD0, 0x41, 0xD2, 0x82, 0x5D}, {0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x09}},
{{0xC6, 0x3A, 0x1C, 0x25, 0x63, 0x5A, 0x2F, 0x0E}, {0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x0B}},
{{0xD9, 0x0E, 0xD7, 0x30, 0xE2, 0xAD, 0xA9, 0x87}, {0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x0F}},
{{0x6B, 0x81, 0xC6, 0xD1, 0x05, 0x09, 0x87, 0x1E}, {0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x17}},
{{0xB4, 0xA7, 0x1E, 0x02, 0x54, 0x37, 0x43, 0x35}, {0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x27}},
{{0x45, 0x14, 0x7C, 0x7F, 0xE0, 0xDE, 0x09, 0x65}, {0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x47}},
{{0x78, 0xB0, 0xF5, 0x20, 0x8B, 0x7D, 0xF3, 0xDD}, {0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xFE, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x88, 0xB3, 0x3C, 0xE1, 0xF7, 0x87, 0x42, 0xA1}, {0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0xFC, 0x06, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x11, 0x2F, 0xB2, 0xF7, 0xE2, 0xB2, 0x4F, 0x6E}, {0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0xFA, 0x08, 0x01, 0x03, 0x05, 0x07}},
{{0x25, 0x56, 0x4E, 0xC6, 0xEB, 0x2D, 0x74, 0x5B}, {0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0xF8, 0x01, 0x03, 0x05, 0x07}},
{{0x7E, 0x98, 0x37, 0xF9, 0x80, 0x8F, 0x09, 0x82}, {0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0xFF, 0x03, 0x05, 0x07}},
{{0xF9, 0xB5, 0x62, 0x3B, 0xD8, 0x7B, 0x3C, 0x3F}, {0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0xFD, 0x05, 0x07}},
{{0x29, 0xC5, 0x2B, 0xFA, 0xD1, 0xFC, 0x5C, 0xC7}, {0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0xFB, 0x07}},
{{0xC1, 0xA3, 0x09, 0x71, 0xBD, 0x8E, 0xAF, 0x2F}, {0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x06, 0x08, 0x01, 0x03, 0x05, 0xF9}},
{{0xB6, 0xDD, 0xD1, 0xAD, 0xAA, 0x15, 0x6F, 0x29}, {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x03, 0x05, 0x02, 0x07, 0x04, 0x06, 0x08}},
{{0x65, 0x34, 0x03, 0x19, 0x17, 0xB3, 0xA3, 0x96}, {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x01, 0x06, 0x08, 0x03, 0x05, 0x07}},
{{0xF9, 0x38, 0x43, 0x56, 0x52, 0xE5, 0xB1, 0xA9}, {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x02, 0x04, 0x06, 0x08, 0x03, 0x05, 0x07}},
{{0xA4,0xA0,0xAF,0xDA,0x48,0xB0,0xA1,0x10},{0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x01,0x02,0x04,0x06,0x03,0x08,0x05,0x07}},
{{0x55,0x15,0x8A,0x0D,0x48,0x29,0x01,0xD8},{0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x04,0x01,0x06,0x03,0x05,0x08,0x07}},
{{0xC4,0x81,0x96,0x7D,0xA3,0xB7,0x73,0x50},{0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x01,0x02,0x03,0x05,0x04,0x06,0x08,0x07}},
{{0x36,0x73,0xDF,0xC1,0x1B,0x98,0xA8,0x1D},{0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x01,0x02,0x03,0x04,0x05,0x06,0x08,0x07}},
{{0xCE,0xE0,0xB3,0x1B,0x41,0xEB,0x15,0x12},{0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x01,0x02,0x03,0x04,0x06,0x05,0x08,0x07}},
{{0},{0},{0}}
{{0xA4, 0xA0, 0xAF, 0xDA, 0x48, 0xB0, 0xA1, 0x10}, {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x02, 0x04, 0x06, 0x03, 0x08, 0x05, 0x07}},
{{0x55, 0x15, 0x8A, 0x0D, 0x48, 0x29, 0x01, 0xD8}, {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x02, 0x04, 0x01, 0x06, 0x03, 0x05, 0x08, 0x07}},
{{0xC4, 0x81, 0x96, 0x7D, 0xA3, 0xB7, 0x73, 0x50}, {0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x02, 0x03, 0x05, 0x04, 0x06, 0x08, 0x07}},
{{0x36, 0x73, 0xDF, 0xC1, 0x1B, 0x98, 0xA8, 0x1D}, {0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x07}},
{{0xCE, 0xE0, 0xB3, 0x1B, 0x41, 0xEB, 0x15, 0x12}, {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x02, 0x03, 0x04, 0x06, 0x05, 0x08, 0x07}},
{{0}, {0}, {0}}
};
int testKeyDiversificationWithMasterkeyTestcases() {
int testKeyDiversificationWithMasterkeyTestcases()
{
int i, error = 0;
uint8_t empty[8] = {0};
PrintAndLogDevice(INFO, "Testing encryption/decryption");
for (i = 0; memcmp(testcases+i, empty, 8); i++)
for (i = 0; memcmp(testcases + i, empty, 8); i++)
error += testDES(testcases[i], ctx_enc, ctx_dec);
if (error)
@@ -587,8 +584,9 @@ int testKeyDiversificationWithMasterkeyTestcases() {
return error;
}
void print64bits(char*name, uint64_t val) {
printf("%s%08x%08x\n", name, (uint32_t) (val >> 32) ,(uint32_t) (val & 0xFFFFFFFF));
void print64bits(char *name, uint64_t val)
{
printf("%s%08x%08x\n", name, (uint32_t)(val >> 32), (uint32_t)(val & 0xFFFFFFFF));
}
uint64_t testCryptedCSN(uint64_t crypted_csn, uint64_t expected)
@@ -596,20 +594,21 @@ uint64_t testCryptedCSN(uint64_t crypted_csn, uint64_t expected)
int retval = 0;
uint8_t result[8] = {0};
if (debug_print) PrintAndLogDevice(DEBUG, "debug_print %d", debug_print);
if (debug_print) print64bits(" {csn} ", crypted_csn );
if (debug_print) print64bits(" {csn} ", crypted_csn);
uint64_t crypted_csn_swapped = swapZvalues(crypted_csn);
if (debug_print) print64bits(" {csn-revz} ", crypted_csn_swapped);
hash0(crypted_csn, result);
uint64_t resultbyte = x_bytes_to_num(result,8 );
if (debug_print) print64bits(" hash0 " , resultbyte );
uint64_t resultbyte = x_bytes_to_num(result, 8);
if (debug_print) print64bits(" hash0 ", resultbyte);
if (resultbyte != expected ) {
if (resultbyte != expected) {
if (debug_print) {
PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(FAILED, "FAIL!");
print64bits(" expected " , expected );
PrintAndLogDevice(NORMAL, "\n");
PrintAndLogDevice(FAILED, "FAIL!");
print64bits(" expected ", expected);
}
retval = 1;
} else {
@@ -618,7 +617,8 @@ uint64_t testCryptedCSN(uint64_t crypted_csn, uint64_t expected)
return retval;
}
int testDES2(uint64_t csn, uint64_t expected) {
int testDES2(uint64_t csn, uint64_t expected)
{
uint8_t result[8] = {0};
uint8_t input[8] = {0};
@@ -628,10 +628,10 @@ int testDES2(uint64_t csn, uint64_t expected) {
mbedtls_des_crypt_ecb(&ctx_enc, input, result);
uint64_t crypt_csn = x_bytes_to_num(result, 8);
print64bits(" {csn} ", crypt_csn );
print64bits(" expected ", expected );
print64bits(" {csn} ", crypt_csn);
print64bits(" expected ", expected);
if( expected == crypt_csn ) {
if (expected == crypt_csn) {
PrintAndLogDevice(SUCCESS, "OK");
return 0;
} else {
@@ -644,49 +644,51 @@ int testDES2(uint64_t csn, uint64_t expected) {
* @brief doTestsWithKnownInputs
* @return
*/
int doTestsWithKnownInputs() {
int doTestsWithKnownInputs()
{
// KSel from http://www.proxmark.org/forum/viewtopic.php?pid=10977#p10977
int errors = 0;
PrintAndLogDevice(SUCCESS, "Testing DES encryption");
uint8_t key[8] = {0x6c,0x8d,0x44,0xf9,0x2a,0x2d,0x01,0xbf};
uint8_t key[8] = {0x6c, 0x8d, 0x44, 0xf9, 0x2a, 0x2d, 0x01, 0xbf};
mbedtls_des_setkey_enc( &ctx_enc, key);
testDES2(0xbbbbaaaabbbbeeee,0xd6ad3ca619659e6b);
mbedtls_des_setkey_enc(&ctx_enc, key);
testDES2(0xbbbbaaaabbbbeeee, 0xd6ad3ca619659e6b);
PrintAndLogDevice(SUCCESS, "Testing hashing algorithm");
errors += testCryptedCSN(0x0102030405060708,0x0bdd6512073c460a);
errors += testCryptedCSN(0x1020304050607080,0x0208211405f3381f);
errors += testCryptedCSN(0x1122334455667788,0x2bee256d40ac1f3a);
errors += testCryptedCSN(0xabcdabcdabcdabcd,0xa91c9ec66f7da592);
errors += testCryptedCSN(0xbcdabcdabcdabcda,0x79ca5796a474e19b);
errors += testCryptedCSN(0xcdabcdabcdabcdab,0xa8901b9f7ec76da4);
errors += testCryptedCSN(0xdabcdabcdabcdabc,0x357aa8e0979a5b8d);
errors += testCryptedCSN(0x21ba6565071f9299,0x34e80f88d5cf39ea);
errors += testCryptedCSN(0x14e2adfc5bb7e134,0x6ac90c6508bd9ea3);
errors += testCryptedCSN(0x0102030405060708, 0x0bdd6512073c460a);
errors += testCryptedCSN(0x1020304050607080, 0x0208211405f3381f);
errors += testCryptedCSN(0x1122334455667788, 0x2bee256d40ac1f3a);
errors += testCryptedCSN(0xabcdabcdabcdabcd, 0xa91c9ec66f7da592);
errors += testCryptedCSN(0xbcdabcdabcdabcda, 0x79ca5796a474e19b);
errors += testCryptedCSN(0xcdabcdabcdabcdab, 0xa8901b9f7ec76da4);
errors += testCryptedCSN(0xdabcdabcdabcdabc, 0x357aa8e0979a5b8d);
errors += testCryptedCSN(0x21ba6565071f9299, 0x34e80f88d5cf39ea);
errors += testCryptedCSN(0x14e2adfc5bb7e134, 0x6ac90c6508bd9ea3);
if (errors)
PrintAndLogDevice(FAILED, "%d errors occurred (9 testcases)", errors);
else
PrintAndLogDevice(SUCCESS, "Hashing seems to work (9 testcases)" );
PrintAndLogDevice(SUCCESS, "Hashing seems to work (9 testcases)");
return errors;
}
static bool readKeyFile(uint8_t key[8]) {
static bool readKeyFile(uint8_t key[8])
{
bool retval = false;
//Test a few variants
char filename[30] = {0};
if (fileExists("iclass_key.bin")){
if (fileExists("iclass_key.bin")) {
sprintf(filename, "%s.bin", "iclass_key");
} else if (fileExists("loclass/iclass_key.bin")){
} else if (fileExists("loclass/iclass_key.bin")) {
sprintf(filename, "%s.bin", "loclass/iclass_key");
} else if (fileExists("client/loclass/iclass_key.bin")){
} else if (fileExists("client/loclass/iclass_key.bin")) {
sprintf(filename, "%s.bin", "client/loclass/iclass_key");
}
if ( strlen(filename) == 0 )
if (strlen(filename) == 0)
return retval;
FILE *f = fopen(filename, "rb");
@@ -694,7 +696,7 @@ static bool readKeyFile(uint8_t key[8]) {
return retval;
size_t bytes_read = fread(key, sizeof(uint8_t), 8, f);
if ( bytes_read == 8)
if (bytes_read == 8)
retval = true;
if (f)
@@ -702,7 +704,8 @@ static bool readKeyFile(uint8_t key[8]) {
return retval;
}
int doKeyTests(uint8_t debuglevel) {
int doKeyTests(uint8_t debuglevel)
{
debug_print = debuglevel;
PrintAndLogDevice(INFO, "Checking if the master key is present (iclass_key.bin)...");
@@ -723,8 +726,8 @@ int doKeyTests(uint8_t debuglevel) {
PrintAndLogDevice(SUCCESS, "Key present");
PrintAndLogDevice(SUCCESS, "Checking key parity...");
des_checkParity(key);
mbedtls_des_setkey_enc( &ctx_enc, key);
mbedtls_des_setkey_dec( &ctx_dec, key);
mbedtls_des_setkey_enc(&ctx_enc, key);
mbedtls_des_setkey_dec(&ctx_dec, key);
// Test hashing functions
PrintAndLogDevice(SUCCESS, "The following tests require the correct 8-byte master key");
testKeyDiversificationWithMasterkeyTestcases();

View File

@@ -54,8 +54,7 @@ int unitTests()
errors += testMAC();
errors += doKeyTests(0);
errors += testElite();
if(errors)
{
if (errors) {
PrintAndLogDevice(NORMAL, "OBS! There were errors!!!");
}
return errors;
@@ -78,7 +77,7 @@ int showHelp()
return 0;
}
int main (int argc, char **argv)
int main(int argc, char **argv)
{
PrintAndLogDevice(NORMAL, "IClass Cipher version 1.2, Copyright (C) 2014 Martin Holst Swende\n");
PrintAndLogDevice(NORMAL, "Comes with ABSOLUTELY NO WARRANTY");
@@ -96,28 +95,27 @@ int main (int argc, char **argv)
char *fileName = NULL;
int c;
while ((c = getopt (argc, argv, "thf:")) != -1)
switch (c)
{
case 't':
return unitTests();
case 'h':
return showHelp();
case 'f':
fileName = optarg;
return bruteforceFileNoKeys(fileName);
case '?':
if (optopt == 'f')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
//default:
//showHelp();
while ((c = getopt(argc, argv, "thf:")) != -1)
switch (c) {
case 't':
return unitTests();
case 'h':
return showHelp();
case 'f':
fileName = optarg;
return bruteforceFileNoKeys(fileName);
case '?':
if (optopt == 'f')
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint(optopt))
fprintf(stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf(stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
//default:
//showHelp();
}
showHelp();
return 0;