X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/de867f502fd3611678d3ed26f69eb6b141f542fc..7779d73c71c248e05574b85f82df4e4f543d522e:/client/nonce2key.c?ds=sidebyside diff --git a/client/nonce2key.c b/client/nonce2key.c new file mode 100644 index 00000000..acd551e4 --- /dev/null +++ b/client/nonce2key.c @@ -0,0 +1,137 @@ +//----------------------------------------------------------------------------- +// Merlok - June 2011 +// Roel - Dec 2009 +// Unknown author +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// MIFARE Darkside hack +//----------------------------------------------------------------------------- + +#include "nonce2key.h" + +#include +#include +#include +#include "mifarehost.h" +#include "util.h" +#include "crapto1/crapto1.h" + +// recover key from 2 different reader responses on same tag challenge +bool mfkey32(nonces_t data, uint64_t *outputkey) { + struct Crypto1State *s,*t; + uint64_t outkey = 0; + uint64_t key = 0; // recovered key + bool isSuccess = false; + uint8_t counter = 0; + + uint64_t t1 = msclock(); + + s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0); + + for(t = s; t->odd | t->even; ++t) { + lfsr_rollback_word(t, 0, 0); + lfsr_rollback_word(t, data.nr, 1); + lfsr_rollback_word(t, data.cuid ^ data.nonce, 0); + crypto1_get_lfsr(t, &key); + crypto1_word(t, data.cuid ^ data.nonce, 0); + crypto1_word(t, data.nr2, 1); + if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce, 64))) { + //PrintAndLog("Found Key: [%012" PRIx64 "]",key); + outkey = key; + counter++; + if (counter == 20) break; + } + } + isSuccess = (counter == 1); + t1 = msclock() - t1; + //if ( t1 > 0 ) PrintAndLog("Time in mfkey32: %.1f seconds \nFound %d possible keys", (float)t1/1000.0, counter); + *outputkey = ( isSuccess ) ? outkey : 0; + crypto1_destroy(s); + /* //un-comment to save all keys to a stats.txt file + FILE *fout; + if ((fout = fopen("stats.txt","ab")) == NULL) { + PrintAndLog("Could not create file name stats.txt"); + return 1; + } + fprintf(fout, "mfkey32,%d,%08x,%d,%s,%04x%08x,%.0Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t)(outkey>>32) & 0xFFFF,(uint32_t)(outkey&0xFFFFFFFF),(long double)t1); + fclose(fout); + */ + return isSuccess; +} + +// recover key from 2 reader responses on 2 different tag challenges +bool mfkey32_moebius(nonces_t data, uint64_t *outputkey) { + struct Crypto1State *s, *t; + uint64_t outkey = 0; + uint64_t key = 0; // recovered key + bool isSuccess = false; + int counter = 0; + + //PrintAndLog("Enter mfkey32_moebius"); + uint64_t t1 = msclock(); + + s = lfsr_recovery32(data.ar ^ prng_successor(data.nonce, 64), 0); + + for(t = s; t->odd | t->even; ++t) { + lfsr_rollback_word(t, 0, 0); + lfsr_rollback_word(t, data.nr, 1); + lfsr_rollback_word(t, data.cuid ^ data.nonce, 0); + crypto1_get_lfsr(t, &key); + + crypto1_word(t, data.cuid ^ data.nonce2, 0); + crypto1_word(t, data.nr2, 1); + if (data.ar2 == (crypto1_word(t, 0, 0) ^ prng_successor(data.nonce2, 64))) { + //PrintAndLog("Found Key: [%012" PRIx64 "]",key); + outkey=key; + ++counter; + if (counter==20) + break; + } + } + isSuccess = (counter == 1); + t1 = msclock() - t1; + // PrintAndLog("Time in mfkey32_moebius: %.1f seconds \nFound %d possible keys", (float)t1/1000.0, counter); + *outputkey = ( isSuccess ) ? outkey : 0; + crypto1_destroy(s); + /* // un-comment to output all keys to stats.txt + FILE *fout; + if ((fout = fopen("stats.txt","ab")) == NULL) { + PrintAndLog("Could not create file name stats.txt"); + return 1; + } + fprintf(fout, "moebius,%d,%08x,%d,%s,%04x%08x,%0.Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t) (outkey>>32),(uint32_t)(outkey&0xFFFFFFFF),(long double)t1); + fclose(fout); + */ + return isSuccess; +} + +// recover key from reader response and tag response of one authentication sequence +int mfkey64(nonces_t data, uint64_t *outputkey){ + uint64_t key = 0; // recovered key + uint32_t ks2; // keystream used to encrypt reader response + uint32_t ks3; // keystream used to encrypt tag response + struct Crypto1State *revstate; + + // PrintAndLog("Enter mfkey64"); + uint64_t t1 = msclock(); + + // Extract the keystream from the messages + ks2 = data.ar ^ prng_successor(data.nonce, 64); + ks3 = data.at ^ prng_successor(data.nonce, 96); + revstate = lfsr_recovery64(ks2, ks3); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, data.nr, 1); + lfsr_rollback_word(revstate, data.cuid ^ data.nonce, 0); + crypto1_get_lfsr(revstate, &key); + // PrintAndLog("Found Key: [%012" PRIx64 "]", key); + crypto1_destroy(revstate); + *outputkey = key; + + t1 = msclock() - t1; + // PrintAndLog("Time in mfkey64: %.1f seconds \n", (float)t1/1000.0); + return 0; +}