X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/0ce5620254d53745397f06b349f7c4d35c1f41d8..8361ba2266a46d4d2962f3b55779fa0181e11c6f:/client/loclass/ikeys.c diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 4749181e..a870f86d 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -1,15 +1,23 @@ /***************************************************************************** - * This file is part of iClassCipher. It is a reconstructon of the cipher engine + * WARNING + * + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * + ***************************************************************************** + * + * This file is part of loclass. It is a reconstructon of the cipher engine * used in iClass, and RFID techology. * * The implementation is based on the work performed by * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and * Milosch Meriac in the paper "Dismantling IClass". * - * This is a reference implementation of iclass key diversification. I'm sure it can be - * optimized heavily. It is written for ease of understanding and correctness, please take it - * and tweak it and make a super fast version instead, using this for testing and verification. - * Copyright (C) 2014 Martin Holst Swende * * This is free software: you can redistribute it and/or modify @@ -22,11 +30,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with IClassCipher. If not, see . + * along with loclass. If not, see . + * + * + * ****************************************************************************/ /** - From "Dismantling iclass": This section describes in detail the built-in key diversification algorithm of iClass. Besides the obvious purpose of deriving a card key from a master key, this @@ -46,10 +56,7 @@ From "Dismantling iclass": similar key bytes, which could produce a strong bias in the cipher. Finally, the output of hash0 is the diversified card key k = k [0] , . . . , k [7] ∈ (F 82 ) 8 . - **/ - - #include #include #include @@ -70,7 +77,7 @@ static int debug_print = 0; * @brief The key diversification algorithm uses 6-bit bytes. * This implementation uses 64 bit uint to pack seven of them into one * variable. When they are there, they are placed as follows: - * XXXX XXXX N0 .... N7, occupying the lsat 48 bits. + * XXXX XXXX N0 .... N7, occupying the last 48 bits. * * This function picks out one from such a collection * @param all @@ -134,38 +141,28 @@ uint64_t swapZvalues(uint64_t c) */ uint64_t ck(int i, int j, uint64_t z) { - - if(i == 1 && j == -1) - { + 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); } - 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++) - { + for(c = 0; c < 4; c++) { uint8_t val = getSixBitByte(z,c); - if(c == i) - { + if (c == i) pushbackSixBitByte(&newz, j, c); - }else - { + else pushbackSixBitByte(&newz, val, c); - } } return ck(i,j-1,newz); - }else - { + } else { return ck(i,j-1,z); } } @@ -208,9 +205,8 @@ uint64_t check(uint64_t z) void permute(BitstreamIn *p_in, uint64_t z,int l,int r, BitstreamOut* out) { if(bitsLeft(p_in) == 0) - { return; - } + bool pn = tailBit(p_in); if( pn ) // pn = 1 { @@ -226,10 +222,9 @@ void permute(BitstreamIn *p_in, uint64_t z,int l,int r, BitstreamOut* out) permute(p_in,z,l,r+1,out); } } -void printbegin() -{ - if(debug_print <2) - return ; +void printbegin() { + if (debug_print < 2) + return; prnlog(" | x| y|z0|z1|z2|z3|z4|z5|z6|z7|"); } @@ -237,17 +232,15 @@ void printbegin() void printState(char* desc, uint64_t c) { if(debug_print < 2) - return ; + return; printf("%s : ", desc); 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++) - { + int i; + for(i = 0; i < 8; i++) printf(" %02x", getSixBitByte(c,i)); - } printf("\n"); } @@ -287,23 +280,19 @@ void hash0(uint64_t c, uint8_t k[8]) _zn = (zn % (63-n)) + n; _zn4 = (zn4 % (64-n)) + n; - pushbackSixBitByte(&zP, _zn,n); pushbackSixBitByte(&zP, _zn4,n+4); - } + printState("0|0|z'",zP); uint64_t zCaret = check(zP); printState("0|0|z^",zP); - uint8_t p = pi[x % 35]; if(x & 1) //Check if x7 is 1 - { p = ~p; - } if(debug_print >= 2) prnlog("p:%02x", p); @@ -324,9 +313,8 @@ void hash0(uint64_t c, uint8_t k[8]) int i; int zerocounter =0 ; - for(i =0 ; i < 8 ; i++) + 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 @@ -366,9 +354,9 @@ void hash0(uint64_t c, uint8_t k[8]) k[i] |= zTilde_i & 0x7E; k[i] |= (~p_i) & 1; } - if((k[i] & 1 )== 0) + if ((k[i] & 1 )== 0) { - zerocounter ++; + zerocounter++; } } } @@ -380,7 +368,6 @@ 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 des_setkey_enc( &ctx_enc, key); @@ -396,13 +383,8 @@ void diversifyKey(uint8_t csn[8], uint8_t key[8], uint8_t div_key[8]) hash0(crypt_csn,div_key); } - - - - void testPermute() { - uint64_t x = 0; pushbackSixBitByte(&x,0x00,0); pushbackSixBitByte(&x,0x01,1); @@ -454,7 +436,6 @@ typedef struct uint8_t div_key[8]; } Testcase; - int testDES(Testcase testcase, des_context ctx_enc, des_context ctx_dec) { uint8_t des_encrypted_csn[8] = {0}; @@ -492,7 +473,6 @@ int testDES(Testcase testcase, des_context ctx_enc, des_context ctx_dec) printarr("hash0 ", div_key, 8); printarr("Expected", testcase.div_key, 8); retval = 1; - } return retval; } @@ -505,27 +485,20 @@ bool des_getParityBitFromKey(uint8_t key) 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++) - { + int fails = 0; + for(i = 0; i < 8; i++) { bool parity = des_getParityBitFromKey(key[i]); - if(parity != (key[i] & 0x1)) - { + if (parity != (key[i] & 0x1)) { fails++; - prnlog("[+] parity1 fail, byte %d [%02x] was %d, should be %d",i,key[i],(key[i] & 0x1),parity); + prnlog("[+] parity1 fail, byte %d [%02x] was %d, should be %d", i, key[i], (key[i] & 0x1), parity); } } if(fails) - { prnlog("[+] parity fails: %d", fails); - }else - { + else prnlog("[+] Key syntax is with parity bits inside each byte"); - } } Testcase testcases[] ={ @@ -599,32 +572,24 @@ Testcase testcases[] ={ {{0},{0},{0}} }; - -int testKeyDiversificationWithMasterkeyTestcases() -{ - +int testKeyDiversificationWithMasterkeyTestcases() { int error = 0; int i; - uint8_t empty[8]={0}; + prnlog("[+} Testing encryption/decryption"); - for (i = 0; memcmp(testcases+i,empty,8) ; i++) { - error += testDES(testcases[i],ctx_enc, ctx_dec); - } - if(error) - { + for (i = 0; memcmp(testcases+i, empty, 8); i++) + error += testDES(testcases[i], ctx_enc, ctx_dec); + + if (error) prnlog("[+] %d errors occurred (%d testcases)", error, i); - }else - { + else prnlog("[+] Hashing seems to work (%d testcases)", i); - } return error; } - -void print64bits(char*name, uint64_t val) -{ +void print64bits(char*name, uint64_t val) { printf("%s%08x%08x\n",name,(uint32_t) (val >> 32) ,(uint32_t) (val & 0xFFFFFFFF)); } @@ -643,24 +608,19 @@ uint64_t testCryptedCSN(uint64_t crypted_csn, uint64_t expected) uint64_t resultbyte = x_bytes_to_num(result,8 ); if(debug_print) print64bits(" hash0 " , resultbyte ); - if(resultbyte != expected ) - { - + if(resultbyte != expected ) { if(debug_print) { prnlog("\n[+] FAIL!"); print64bits(" expected " , expected ); } retval = 1; - - }else - { - if(debug_print) prnlog(" [OK]"); + } else { + if (debug_print) prnlog(" [OK]"); } 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}; @@ -673,12 +633,10 @@ int testDES2(uint64_t csn, uint64_t expected) print64bits(" {csn} ", crypt_csn ); print64bits(" expected ", expected ); - if( expected == crypt_csn ) - { + if( expected == crypt_csn ) { prnlog("[+] OK"); return 0; - }else - { + } else { return 1; } } @@ -688,14 +646,10 @@ 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; prnlog("[+] Testing DES encryption"); -// uint8_t key[8] = {0x6c,0x8d,0x44,0xf9,0x2a,0x2d,0x01,0xbf}; - prnlog("[+] Testing foo"); uint8_t key[8] = {0x6c,0x8d,0x44,0xf9,0x2a,0x2d,0x01,0xbf}; des_setkey_enc( &ctx_enc, key); @@ -713,32 +667,26 @@ int doTestsWithKnownInputs() errors += testCryptedCSN(0x21ba6565071f9299,0x34e80f88d5cf39ea); errors += testCryptedCSN(0x14e2adfc5bb7e134,0x6ac90c6508bd9ea3); - if(errors) - { + if (errors) prnlog("[+] %d errors occurred (9 testcases)", errors); - }else - { + else prnlog("[+] Hashing seems to work (9 testcases)" ); - } return errors; } -int readKeyFile(uint8_t key[8]) -{ - - FILE *f; +int readKeyFile(uint8_t key[8]) { int retval = 1; - f = fopen("iclass_key.bin", "rb"); + FILE *f = fopen("iclass_key.bin", "rb"); + if (!f) + return 0; + + size_t bytes_read = fread(key, sizeof(uint8_t), 8, f); + if ( bytes_read == 1) + retval = 0; + if (f) - { - if(fread(key, sizeof(uint8_t), 8, f) == 1) - { - retval = 0; - } fclose(f); - } return retval; - } @@ -748,25 +696,20 @@ int doKeyTests(uint8_t debuglevel) prnlog("[+] Checking if the master key is present (iclass_key.bin)..."); uint8_t key[8] = {0}; - if(readKeyFile(key)) - { + if (readKeyFile(key)) { prnlog("[+] Master key not present, will not be able to do all testcases"); - }else - { + } else { //Test if it's the right key... uint8_t i; uint8_t j = 0; - for(i =0 ; i < sizeof(key) ; i++) + for (i = 0; i < sizeof(key); i++) j += key[i]; - - if(j != 185) - { + + if (j != 185) { prnlog("[+] A key was loaded, but it does not seem to be the correct one. Aborting these tests"); - }else - { + } else { prnlog("[+] Key present"); - prnlog("[+] Checking key parity..."); des_checkParity(key); des_setkey_enc( &ctx_enc, key); @@ -854,29 +797,20 @@ void modifyKey_put_parity_allover(uint8_t * key, uint8_t* output) BitstreamOut out = { output, 0,0}; BitstreamIn in = {key, 0,0}; unsigned int bbyte, bbit; - for(bbit =0 ; bbit < 56 ; bbit++) - { - - if( bbit > 0 && bbit % 7 == 0) - { + for(bbit =0 ; bbit < 56 ; bbit++) { + if( bbit > 0 && bbit % 7 == 0) { pushBit(&out,!parity); parity = 0; } bool bit = headBit(&in); pushBit(&out,bit ); parity ^= bit; - } pushBit(&out, !parity); - if( des_key_check_key_parity(output)) - { printf("modifyKey_put_parity_allover fail, DES key invalid parity!"); - } - } - */